Skip to content

Commit 2cdc915

Browse files
committed
drivers: video: gc2145: switch to video CCI library
Reduce the amount of code in the GC2145 driver by switching to the CCI helpers in video_common.c. The batch I2C write functions are not used to avoid increasing the size of the ROM, as struct video_reg is 8 bytes while the ad-hoc struct gc2145_reg is 2 bytes. Signed-off-by: Josuah Demangeon <me@josuah.net>
1 parent 91c0397 commit 2cdc915

File tree

1 file changed

+60
-152
lines changed

1 file changed

+60
-152
lines changed

drivers/video/gc2145.c

Lines changed: 60 additions & 152 deletions
Original file line numberDiff line numberDiff line change
@@ -12,32 +12,37 @@
1212
#include <zephyr/drivers/video-controls.h>
1313
#include <zephyr/drivers/i2c.h>
1414
#include <zephyr/drivers/gpio.h>
15-
1615
#include <zephyr/logging/log.h>
16+
17+
#include "video_common.h"
18+
1719
LOG_MODULE_REGISTER(video_gc2145, CONFIG_VIDEO_LOG_LEVEL);
1820

19-
#define GC2145_REG_AMODE1 0x17
21+
#define GC2145_REG8(addr) ((addr) | VIDEO_REG_ADDR8_DATA8)
22+
#define GC2145_REG16(addr) ((addr) | VIDEO_REG_ADDR8_DATA16_LE)
23+
24+
#define GC2145_REG_AMODE1 GC2145_REG8(0x17)
2025
#define GC2145_AMODE1_WINDOW_MASK 0xFC
21-
#define GC2145_REG_AMODE1_DEF 0x14
22-
#define GC2145_REG_OUTPUT_FMT 0x84
23-
#define GC2145_REG_OUTPUT_FMT_MASK 0x1F
24-
#define GC2145_REG_OUTPUT_FMT_RGB565 0x06
25-
#define GC2145_REG_OUTPUT_FMT_YCBYCR 0x02
26-
#define GC2145_REG_SYNC_MODE 0x86
27-
#define GC2145_REG_SYNC_MODE_DEF 0x23
28-
#define GC2145_REG_SYNC_MODE_COL_SWITCH 0x10
29-
#define GC2145_REG_SYNC_MODE_ROW_SWITCH 0x20
30-
#define GC2145_REG_RESET 0xFE
31-
#define GC2145_REG_SW_RESET 0x80
32-
#define GC2145_PID_VAL 0x21
33-
#define GC2145_REV_VAL 0x55
26+
#define GC2145_REG_AMODE1_DEF GC2145_REG8(0x14)
27+
#define GC2145_REG_OUTPUT_FMT GC2145_REG8(0x84)
28+
#define GC2145_REG_OUTPUT_FMT_MASK GC2145_REG8(0x1F)
29+
#define GC2145_REG_OUTPUT_FMT_RGB565 GC2145_REG8(0x06)
30+
#define GC2145_REG_OUTPUT_FMT_YCBYCR GC2145_REG8(0x02)
31+
#define GC2145_REG_SYNC_MODE GC2145_REG8(0x86)
32+
#define GC2145_REG_SYNC_MODE_DEF GC2145_REG8(0x23)
33+
#define GC2145_REG_SYNC_MODE_COL_SWITCH GC2145_REG8(0x10)
34+
#define GC2145_REG_SYNC_MODE_ROW_SWITCH GC2145_REG8(0x20)
35+
#define GC2145_REG_RESET GC2145_REG8(0xFE)
36+
#define GC2145_REG_SW_RESET GC2145_REG8(0x80)
37+
#define GC2145_REG_CHIP_ID GC2145_REG8(0xF0)
38+
#define GC2145_CHIP_ID 0x2155
3439
#define GC2145_SET_P0_REGS 0x00
35-
#define GC2145_REG_CROP_ENABLE 0x90
40+
#define GC2145_REG_CROP_ENABLE GC2145_REG8(0x90)
3641
#define GC2145_CROP_SET_ENABLE 0x01
37-
#define GC2145_REG_BLANK_WINDOW_BASE 0x09
38-
#define GC2145_REG_WINDOW_BASE 0x91
39-
#define GC2145_REG_SUBSAMPLE 0x99
40-
#define GC2145_REG_SUBSAMPLE_MODE 0x9A
42+
#define GC2145_REG_BLANK_WINDOW_BASE GC2145_REG8(0x09)
43+
#define GC2145_REG_WINDOW_BASE GC2145_REG8(0x91)
44+
#define GC2145_REG_SUBSAMPLE GC2145_REG8(0x99)
45+
#define GC2145_REG_SUBSAMPLE_MODE GC2145_REG8(0x9A)
4146
#define GC2145_SUBSAMPLE_MODE_SMOOTH 0x0E
4247

4348
#define UXGA_HSIZE 1600
@@ -105,8 +110,8 @@ static const struct gc2145_reg default_regs[] = {
105110
{0x81, 0x26},
106111
{0x82, 0xfa},
107112
{0x83, 0x00},
108-
{GC2145_REG_OUTPUT_FMT, 0x06},
109-
{GC2145_REG_SYNC_MODE, 0x23},
113+
{(uint8_t)GC2145_REG_OUTPUT_FMT, 0x06},
114+
{(uint8_t)GC2145_REG_SYNC_MODE, 0x23},
110115
{0x88, 0x03},
111116
{0x89, 0x03},
112117
{0x85, 0x08},
@@ -197,7 +202,7 @@ static const struct gc2145_reg default_regs[] = {
197202
{0x0c, 0x10},
198203
{0x11, 0x10},
199204
{0x13, 0x68},
200-
{GC2145_REG_OUTPUT_FMT, 0x00},
205+
{(uint8_t)GC2145_REG_OUTPUT_FMT, 0x00},
201206
{0x1c, 0x11},
202207
{0x1e, 0x61},
203208
{0x1f, 0x35},
@@ -228,8 +233,8 @@ static const struct gc2145_reg default_regs[] = {
228233
{0x81, 0x08},
229234
{0x82, 0x05},
230235
{0x83, 0x08},
231-
{GC2145_REG_OUTPUT_FMT, 0x0a},
232-
{GC2145_REG_SYNC_MODE, 0xf0},
236+
{(uint8_t)GC2145_REG_OUTPUT_FMT, 0x0a},
237+
{(uint8_t)GC2145_REG_SYNC_MODE, 0xf0},
233238
{0x87, 0x50},
234239
{0x88, 0x15},
235240
{0x89, 0xb0},
@@ -264,7 +269,7 @@ static const struct gc2145_reg default_regs[] = {
264269
{0x14, 0x27},
265270
{0x15, 0x37},
266271
{0x16, 0x45},
267-
{GC2145_REG_OUTPUT_FMT, 0x53},
272+
{(uint8_t)GC2145_REG_OUTPUT_FMT, 0x53},
268273
{0x18, 0x69},
269274
{0x19, 0x7d},
270275
{0x1a, 0x8f},
@@ -720,54 +725,6 @@ static const struct video_format_cap fmts[] = {
720725
{0},
721726
};
722727

723-
static int gc2145_write_reg(const struct i2c_dt_spec *spec, uint8_t reg_addr, uint8_t value)
724-
{
725-
int ret;
726-
uint8_t tries = 3;
727-
728-
/*
729-
* It rarely happens that the camera does not respond with ACK signal.
730-
* In that case it usually responds on 2nd try but there is a 3rd one
731-
* just to be sure that the connection error is not caused by driver
732-
* itself.
733-
*/
734-
do {
735-
ret = i2c_reg_write_byte_dt(spec, reg_addr, value);
736-
if (!ret) {
737-
return 0;
738-
}
739-
/* If writing failed wait 5ms before next attempt */
740-
k_msleep(5);
741-
} while (tries-- > 0);
742-
743-
LOG_ERR("failed to write 0x%x to 0x%x,", value, reg_addr);
744-
return ret;
745-
}
746-
747-
static int gc2145_read_reg(const struct i2c_dt_spec *spec, uint8_t reg_addr, uint8_t *value)
748-
{
749-
int ret;
750-
uint8_t tries = 3;
751-
752-
/*
753-
* It rarely happens that the camera does not respond with ACK signal.
754-
* In that case it usually responds on 2nd try but there is a 3rd one
755-
* just to be sure that the connection error is not caused by driver
756-
* itself.
757-
*/
758-
do {
759-
ret = i2c_reg_read_byte_dt(spec, reg_addr, value);
760-
if (!ret) {
761-
return 0;
762-
}
763-
/* If writing failed wait 5ms before next attempt */
764-
k_msleep(5);
765-
} while (tries-- > 0);
766-
767-
LOG_ERR("failed to read 0x%x register", reg_addr);
768-
return ret;
769-
}
770-
771728
static int gc2145_write_all(const struct device *dev, const struct gc2145_reg *regs,
772729
uint16_t reg_num)
773730
{
@@ -776,7 +733,7 @@ static int gc2145_write_all(const struct device *dev, const struct gc2145_reg *r
776733
for (uint16_t i = 0; i < reg_num; i++) {
777734
int ret;
778735

779-
ret = gc2145_write_reg(&cfg->i2c, regs[i].addr, regs[i].value);
736+
ret = video_write_cci_reg(&cfg->i2c, GC2145_REG8(regs[i].addr), regs[i].value);
780737
if (ret < 0) {
781738
return ret;
782739
}
@@ -791,7 +748,7 @@ static int gc2145_soft_reset(const struct device *dev)
791748
const struct gc2145_config *cfg = dev->config;
792749

793750
/* Initiate system reset */
794-
ret = gc2145_write_reg(&cfg->i2c, GC2145_REG_RESET, GC2145_REG_SW_RESET);
751+
ret = video_write_cci_reg(&cfg->i2c, GC2145_REG_RESET, GC2145_REG_SW_RESET);
795752

796753
k_msleep(300);
797754

@@ -800,87 +757,49 @@ static int gc2145_soft_reset(const struct device *dev)
800757

801758
static int gc2145_set_ctrl_vflip(const struct device *dev, bool enable)
802759
{
803-
int ret;
804760
const struct gc2145_config *cfg = dev->config;
805-
uint8_t old_value;
806-
807-
ret = gc2145_read_reg(&cfg->i2c, GC2145_REG_AMODE1, &old_value);
808-
if (ret < 0) {
809-
return ret;
810-
}
811761

812762
/* Set the vertical flip state */
813-
return gc2145_write_reg(&cfg->i2c, GC2145_REG_AMODE1,
814-
(old_value & GC2145_AMODE1_WINDOW_MASK) | (enable << 1));
763+
return video_write_cci_field(&cfg->i2c, GC2145_REG_AMODE1, GC2145_AMODE1_WINDOW_MASK,
764+
FIELD_PREP(GC2145_AMODE1_WINDOW_MASK, enable << 1));
815765
}
816766

817767
static int gc2145_set_ctrl_hmirror(const struct device *dev, bool enable)
818768
{
819-
int ret;
820769
const struct gc2145_config *cfg = dev->config;
821-
uint8_t old_value;
822-
823-
ret = gc2145_read_reg(&cfg->i2c, GC2145_REG_AMODE1, &old_value);
824-
if (ret < 0) {
825-
return ret;
826-
}
827770

828771
/* Set the horizontal mirror state */
829-
return gc2145_write_reg(&cfg->i2c, GC2145_REG_AMODE1,
830-
(old_value & GC2145_AMODE1_WINDOW_MASK) | enable);
772+
return video_write_cci_field(&cfg->i2c, GC2145_REG_AMODE1, GC2145_AMODE1_WINDOW_MASK,
773+
FIELD_PREP(GC2145_AMODE1_WINDOW_MASK, enable));
831774
}
832775

833-
static int gc2145_set_window(const struct device *dev, uint16_t reg, uint16_t x, uint16_t y,
834-
uint16_t w, uint16_t h)
776+
static int gc2145_set_window(const struct device *dev, uint32_t reg, uint32_t x_offset,
777+
uint32_t y_offset, uint32_t window_width, uint32_t window_height)
835778
{
836779
int ret;
837780
const struct gc2145_config *cfg = dev->config;
838781

839-
ret = gc2145_write_reg(&cfg->i2c, GC2145_REG_RESET, GC2145_SET_P0_REGS);
782+
ret = video_write_cci_reg(&cfg->i2c, GC2145_REG_RESET, GC2145_SET_P0_REGS);
840783
if (ret < 0) {
841784
return ret;
842785
}
843786

844-
/* Y/row offset */
845-
ret = gc2145_write_reg(&cfg->i2c, reg++, y >> 8);
787+
ret = video_write_cci_reg(&cfg->i2c, GC2145_REG16(reg + 0), y_offset);
846788
if (ret < 0) {
847789
return ret;
848790
}
849791

850-
ret = gc2145_write_reg(&cfg->i2c, reg++, y & 0xff);
792+
ret = video_write_cci_reg(&cfg->i2c, GC2145_REG16(reg + 2), x_offset);
851793
if (ret < 0) {
852794
return ret;
853795
}
854796

855-
/* X/col offset */
856-
ret = gc2145_write_reg(&cfg->i2c, reg++, x >> 8);
797+
ret = video_write_cci_reg(&cfg->i2c, GC2145_REG16(reg + 4), window_height);
857798
if (ret < 0) {
858799
return ret;
859800
}
860801

861-
ret = gc2145_write_reg(&cfg->i2c, reg++, x & 0xff);
862-
if (ret < 0) {
863-
return ret;
864-
}
865-
866-
/* Window height */
867-
ret = gc2145_write_reg(&cfg->i2c, reg++, h >> 8);
868-
if (ret < 0) {
869-
return ret;
870-
}
871-
872-
ret = gc2145_write_reg(&cfg->i2c, reg++, h & 0xff);
873-
if (ret < 0) {
874-
return ret;
875-
}
876-
877-
/* Window width */
878-
ret = gc2145_write_reg(&cfg->i2c, reg++, w >> 8);
879-
if (ret < 0) {
880-
return ret;
881-
}
882-
883-
ret = gc2145_write_reg(&cfg->i2c, reg++, w & 0xff);
802+
ret = video_write_cci_reg(&cfg->i2c, GC2145_REG16(reg + 6), window_width);
884803
if (ret < 0) {
885804
return ret;
886805
}
@@ -891,10 +810,9 @@ static int gc2145_set_window(const struct device *dev, uint16_t reg, uint16_t x,
891810
static int gc2145_set_output_format(const struct device *dev, int output_format)
892811
{
893812
int ret;
894-
uint8_t old_value;
895813
const struct gc2145_config *cfg = dev->config;
896814

897-
ret = gc2145_write_reg(&cfg->i2c, GC2145_REG_RESET, GC2145_SET_P0_REGS);
815+
ret = video_write_cci_reg(&cfg->i2c, GC2145_REG_RESET, GC2145_SET_P0_REGS);
898816
if (ret < 0) {
899817
return ret;
900818
}
@@ -909,13 +827,8 @@ static int gc2145_set_output_format(const struct device *dev, int output_format)
909827
return -ENOTSUP;
910828
}
911829

912-
ret = gc2145_read_reg(&cfg->i2c, GC2145_REG_OUTPUT_FMT, &old_value);
913-
if (ret < 0) {
914-
return ret;
915-
}
916-
917-
ret = gc2145_write_reg(&cfg->i2c, GC2145_REG_OUTPUT_FMT,
918-
(old_value & ~GC2145_REG_OUTPUT_FMT_MASK) | output_format);
830+
ret = video_write_cci_field(&cfg->i2c, GC2145_REG_OUTPUT_FMT, GC2145_REG_OUTPUT_FMT_MASK,
831+
output_format);
919832
if (ret < 0) {
920833
return ret;
921834
}
@@ -967,31 +880,32 @@ static int gc2145_set_resolution(const struct device *dev, uint32_t w, uint32_t
967880
win_y = ((UXGA_VSIZE - win_h) / 2);
968881

969882
/* Set readout window first. */
970-
ret = gc2145_set_window(dev, GC2145_REG_BLANK_WINDOW_BASE, win_x, win_y, win_w + 16,
971-
win_h + 8);
883+
ret = gc2145_set_window(dev, (uint8_t)GC2145_REG_BLANK_WINDOW_BASE, win_x, win_y,
884+
win_w + 16, win_h + 8);
972885
if (ret < 0) {
973886
return ret;
974887
}
975888

976889
/* Set cropping window next. */
977-
ret = gc2145_set_window(dev, GC2145_REG_WINDOW_BASE, x, y, w, h);
890+
ret = gc2145_set_window(dev, (uint8_t)GC2145_REG_WINDOW_BASE, x, y, w, h);
978891
if (ret < 0) {
979892
return ret;
980893
}
981894

982895
/* Enable crop */
983-
ret = gc2145_write_reg(&cfg->i2c, GC2145_REG_CROP_ENABLE, GC2145_CROP_SET_ENABLE);
896+
ret = video_write_cci_reg(&cfg->i2c, GC2145_REG_CROP_ENABLE, GC2145_CROP_SET_ENABLE);
984897
if (ret < 0) {
985898
return ret;
986899
}
987900

988901
/* Set Sub-sampling ratio and mode */
989-
ret = gc2145_write_reg(&cfg->i2c, GC2145_REG_SUBSAMPLE, ((r_ratio << 4) | c_ratio));
902+
ret = video_write_cci_reg(&cfg->i2c, GC2145_REG_SUBSAMPLE, ((r_ratio << 4) | c_ratio));
990903
if (ret < 0) {
991904
return ret;
992905
}
993906

994-
ret = gc2145_write_reg(&cfg->i2c, GC2145_REG_SUBSAMPLE_MODE, GC2145_SUBSAMPLE_MODE_SMOOTH);
907+
ret = video_write_cci_reg(&cfg->i2c, GC2145_REG_SUBSAMPLE_MODE,
908+
GC2145_SUBSAMPLE_MODE_SMOOTH);
995909
if (ret < 0) {
996910
return ret;
997911
}
@@ -1010,21 +924,15 @@ static uint8_t gc2145_check_connection(const struct device *dev)
1010924
{
1011925
int ret;
1012926
const struct gc2145_config *cfg = dev->config;
1013-
uint8_t reg_pid_val;
1014-
uint8_t reg_ver_val;
1015-
1016-
ret = gc2145_read_reg(&cfg->i2c, 0xf0, &reg_pid_val);
1017-
if (ret < 0) {
1018-
return ret;
1019-
}
927+
uint32_t chip_id;
1020928

1021-
ret = gc2145_read_reg(&cfg->i2c, 0xf1, &reg_ver_val);
929+
ret = video_read_cci_reg(&cfg->i2c, GC2145_REG_CHIP_ID, &chip_id);
1022930
if (ret < 0) {
1023931
return ret;
1024932
}
1025933

1026-
if ((reg_ver_val != GC2145_REV_VAL) || (reg_pid_val != GC2145_PID_VAL)) {
1027-
LOG_WRN("Unexpected GC2145 pid: 0x%x or rev: 0x%x", reg_pid_val, reg_ver_val);
934+
if (chip_id != 0x2155) {
935+
LOG_WRN("Unexpected GC2145 chip ID 0x%x", chip_id);
1028936
}
1029937

1030938
return 0;
@@ -1089,8 +997,8 @@ static int gc2145_set_stream(const struct device *dev, bool enable)
1089997
{
1090998
const struct gc2145_config *cfg = dev->config;
1091999

1092-
return enable ? gc2145_write_reg(&cfg->i2c, 0xf2, 0x0f)
1093-
: gc2145_write_reg(&cfg->i2c, 0xf2, 0x00);
1000+
return enable ? video_write_cci_reg(&cfg->i2c, GC2145_REG8(0xf2), 0x0f)
1001+
: video_write_cci_reg(&cfg->i2c, GC2145_REG8(0xf2), 0x00);
10941002
}
10951003

10961004
static int gc2145_get_caps(const struct device *dev, enum video_endpoint_id ep,

0 commit comments

Comments
 (0)