Skip to content

Commit 64c8e7c

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 2846a0a commit 64c8e7c

File tree

1 file changed

+57
-150
lines changed

1 file changed

+57
-150
lines changed

drivers/video/gc2145.c

Lines changed: 57 additions & 150 deletions
Original file line numberDiff line numberDiff line change
@@ -12,30 +12,36 @@
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
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)
3238
#define GC2145_SET_P0_REGS 0x00
33-
#define GC2145_REG_CROP_ENABLE 0x90
39+
#define GC2145_REG_CROP_ENABLE GC2145_REG8(0x90)
3440
#define GC2145_CROP_SET_ENABLE 0x01
35-
#define GC2145_REG_BLANK_WINDOW_BASE 0x09
36-
#define GC2145_REG_WINDOW_BASE 0x91
37-
#define GC2145_REG_SUBSAMPLE 0x99
38-
#define GC2145_REG_SUBSAMPLE_MODE 0x9A
41+
#define GC2145_REG_BLANK_WINDOW_BASE GC2145_REG8(0x09)
42+
#define GC2145_REG_WINDOW_BASE GC2145_REG8(0x91)
43+
#define GC2145_REG_SUBSAMPLE GC2145_REG8(0x99)
44+
#define GC2145_REG_SUBSAMPLE_MODE GC2145_REG8(0x9A)
3945
#define GC2145_SUBSAMPLE_MODE_SMOOTH 0x0E
4046

4147
#define UXGA_HSIZE 1600
@@ -103,8 +109,8 @@ static const struct gc2145_reg default_regs[] = {
103109
{0x81, 0x26},
104110
{0x82, 0xfa},
105111
{0x83, 0x00},
106-
{GC2145_REG_OUTPUT_FMT, 0x06},
107-
{GC2145_REG_SYNC_MODE, 0x23},
112+
{(uint8_t)GC2145_REG_OUTPUT_FMT, 0x06},
113+
{(uint8_t)GC2145_REG_SYNC_MODE, 0x23},
108114
{0x88, 0x03},
109115
{0x89, 0x03},
110116
{0x85, 0x08},
@@ -195,7 +201,7 @@ static const struct gc2145_reg default_regs[] = {
195201
{0x0c, 0x10},
196202
{0x11, 0x10},
197203
{0x13, 0x68},
198-
{GC2145_REG_OUTPUT_FMT, 0x00},
204+
{(uint8_t)GC2145_REG_OUTPUT_FMT, 0x00},
199205
{0x1c, 0x11},
200206
{0x1e, 0x61},
201207
{0x1f, 0x35},
@@ -226,8 +232,8 @@ static const struct gc2145_reg default_regs[] = {
226232
{0x81, 0x08},
227233
{0x82, 0x05},
228234
{0x83, 0x08},
229-
{GC2145_REG_OUTPUT_FMT, 0x0a},
230-
{GC2145_REG_SYNC_MODE, 0xf0},
235+
{(uint8_t)GC2145_REG_OUTPUT_FMT, 0x0a},
236+
{(uint8_t)GC2145_REG_SYNC_MODE, 0xf0},
231237
{0x87, 0x50},
232238
{0x88, 0x15},
233239
{0x89, 0xb0},
@@ -262,7 +268,7 @@ static const struct gc2145_reg default_regs[] = {
262268
{0x14, 0x27},
263269
{0x15, 0x37},
264270
{0x16, 0x45},
265-
{GC2145_REG_OUTPUT_FMT, 0x53},
271+
{(uint8_t)GC2145_REG_OUTPUT_FMT, 0x53},
266272
{0x18, 0x69},
267273
{0x19, 0x7d},
268274
{0x1a, 0x8f},
@@ -718,54 +724,6 @@ static const struct video_format_cap fmts[] = {
718724
{0},
719725
};
720726

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

777-
ret = gc2145_write_reg(&cfg->i2c, regs[i].addr, regs[i].value);
735+
ret = video_write_cci_reg(&cfg->i2c, GC2145_REG8(regs[i].addr), regs[i].value);
778736
if (ret < 0) {
779737
return ret;
780738
}
@@ -789,7 +747,7 @@ static int gc2145_soft_reset(const struct device *dev)
789747
const struct gc2145_config *cfg = dev->config;
790748

791749
/* Initiate system reset */
792-
ret = gc2145_write_reg(&cfg->i2c, GC2145_REG_RESET, GC2145_REG_SW_RESET);
750+
ret = video_write_cci_reg(&cfg->i2c, GC2145_REG_RESET, GC2145_REG_SW_RESET);
793751

794752
k_msleep(300);
795753

@@ -798,87 +756,49 @@ static int gc2145_soft_reset(const struct device *dev)
798756

799757
static int gc2145_set_ctrl_vflip(const struct device *dev, bool enable)
800758
{
801-
int ret;
802759
const struct gc2145_config *cfg = dev->config;
803-
uint8_t old_value;
804-
805-
ret = gc2145_read_reg(&cfg->i2c, GC2145_REG_AMODE1, &old_value);
806-
if (ret < 0) {
807-
return ret;
808-
}
809760

810761
/* Set the vertical flip state */
811-
return gc2145_write_reg(&cfg->i2c, GC2145_REG_AMODE1,
812-
(old_value & GC2145_AMODE1_WINDOW_MASK) | (enable << 1));
762+
return video_write_cci_field(&cfg->i2c, GC2145_REG_AMODE1, GC2145_AMODE1_WINDOW_MASK,
763+
FIELD_PREP(GC2145_AMODE1_WINDOW_MASK, enable << 1));
813764
}
814765

815766
static int gc2145_set_ctrl_hmirror(const struct device *dev, bool enable)
816767
{
817-
int ret;
818768
const struct gc2145_config *cfg = dev->config;
819-
uint8_t old_value;
820-
821-
ret = gc2145_read_reg(&cfg->i2c, GC2145_REG_AMODE1, &old_value);
822-
if (ret < 0) {
823-
return ret;
824-
}
825769

826770
/* Set the horizontal mirror state */
827-
return gc2145_write_reg(&cfg->i2c, GC2145_REG_AMODE1,
828-
(old_value & GC2145_AMODE1_WINDOW_MASK) | enable);
771+
return video_write_cci_field(&cfg->i2c, GC2145_REG_AMODE1, GC2145_AMODE1_WINDOW_MASK,
772+
FIELD_PREP(GC2145_AMODE1_WINDOW_MASK, enable));
829773
}
830774

831-
static int gc2145_set_window(const struct device *dev, uint16_t reg, uint16_t x, uint16_t y,
832-
uint16_t w, uint16_t h)
775+
static int gc2145_set_window(const struct device *dev, uint32_t reg, uint32_t x_offset,
776+
uint32_t y_offset, uint32_t window_width, uint32_t window_height)
833777
{
834778
int ret;
835779
const struct gc2145_config *cfg = dev->config;
836780

837-
ret = gc2145_write_reg(&cfg->i2c, GC2145_REG_RESET, GC2145_SET_P0_REGS);
838-
if (ret < 0) {
839-
return ret;
840-
}
841-
842-
/* Y/row offset */
843-
ret = gc2145_write_reg(&cfg->i2c, reg++, y >> 8);
781+
ret = video_write_cci_reg(&cfg->i2c, GC2145_REG_RESET, GC2145_SET_P0_REGS);
844782
if (ret < 0) {
845783
return ret;
846784
}
847785

848-
ret = gc2145_write_reg(&cfg->i2c, reg++, y & 0xff);
786+
ret = video_write_cci_reg(&cfg->i2c, GC2145_REG16(reg + 0), y_offset);
849787
if (ret < 0) {
850788
return ret;
851789
}
852790

853-
/* X/col offset */
854-
ret = gc2145_write_reg(&cfg->i2c, reg++, x >> 8);
791+
ret = video_write_cci_reg(&cfg->i2c, GC2145_REG16(reg + 2), x_offset);
855792
if (ret < 0) {
856793
return ret;
857794
}
858795

859-
ret = gc2145_write_reg(&cfg->i2c, reg++, x & 0xff);
796+
ret = video_write_cci_reg(&cfg->i2c, GC2145_REG16(reg + 4), window_height);
860797
if (ret < 0) {
861798
return ret;
862799
}
863800

864-
/* Window height */
865-
ret = gc2145_write_reg(&cfg->i2c, reg++, h >> 8);
866-
if (ret < 0) {
867-
return ret;
868-
}
869-
870-
ret = gc2145_write_reg(&cfg->i2c, reg++, h & 0xff);
871-
if (ret < 0) {
872-
return ret;
873-
}
874-
875-
/* Window width */
876-
ret = gc2145_write_reg(&cfg->i2c, reg++, w >> 8);
877-
if (ret < 0) {
878-
return ret;
879-
}
880-
881-
ret = gc2145_write_reg(&cfg->i2c, reg++, w & 0xff);
801+
ret = video_write_cci_reg(&cfg->i2c, GC2145_REG16(reg + 6), window_width);
882802
if (ret < 0) {
883803
return ret;
884804
}
@@ -889,10 +809,9 @@ static int gc2145_set_window(const struct device *dev, uint16_t reg, uint16_t x,
889809
static int gc2145_set_output_format(const struct device *dev, int output_format)
890810
{
891811
int ret;
892-
uint8_t old_value;
893812
const struct gc2145_config *cfg = dev->config;
894813

895-
ret = gc2145_write_reg(&cfg->i2c, GC2145_REG_RESET, GC2145_SET_P0_REGS);
814+
ret = video_write_cci_reg(&cfg->i2c, GC2145_REG_RESET, GC2145_SET_P0_REGS);
896815
if (ret < 0) {
897816
return ret;
898817
}
@@ -907,13 +826,8 @@ static int gc2145_set_output_format(const struct device *dev, int output_format)
907826
return -ENOTSUP;
908827
}
909828

910-
ret = gc2145_read_reg(&cfg->i2c, GC2145_REG_OUTPUT_FMT, &old_value);
911-
if (ret < 0) {
912-
return ret;
913-
}
914-
915-
ret = gc2145_write_reg(&cfg->i2c, GC2145_REG_OUTPUT_FMT,
916-
(old_value & ~GC2145_REG_OUTPUT_FMT_MASK) | output_format);
829+
ret = video_write_cci_field(&cfg->i2c, GC2145_REG_OUTPUT_FMT, GC2145_REG_OUTPUT_FMT_MASK,
830+
output_format);
917831
if (ret < 0) {
918832
return ret;
919833
}
@@ -965,31 +879,32 @@ static int gc2145_set_resolution(const struct device *dev, uint32_t w, uint32_t
965879
win_y = ((UXGA_VSIZE - win_h) / 2);
966880

967881
/* Set readout window first. */
968-
ret = gc2145_set_window(dev, GC2145_REG_BLANK_WINDOW_BASE, win_x, win_y, win_w + 16,
969-
win_h + 8);
882+
ret = gc2145_set_window(dev, (uint8_t)GC2145_REG_BLANK_WINDOW_BASE, win_x, win_y,
883+
win_w + 16, win_h + 8);
970884
if (ret < 0) {
971885
return ret;
972886
}
973887

974888
/* Set cropping window next. */
975-
ret = gc2145_set_window(dev, GC2145_REG_WINDOW_BASE, x, y, w, h);
889+
ret = gc2145_set_window(dev, (uint8_t)GC2145_REG_WINDOW_BASE, x, y, w, h);
976890
if (ret < 0) {
977891
return ret;
978892
}
979893

980894
/* Enable crop */
981-
ret = gc2145_write_reg(&cfg->i2c, GC2145_REG_CROP_ENABLE, GC2145_CROP_SET_ENABLE);
895+
ret = video_write_cci_reg(&cfg->i2c, GC2145_REG_CROP_ENABLE, GC2145_CROP_SET_ENABLE);
982896
if (ret < 0) {
983897
return ret;
984898
}
985899

986900
/* Set Sub-sampling ratio and mode */
987-
ret = gc2145_write_reg(&cfg->i2c, GC2145_REG_SUBSAMPLE, ((r_ratio << 4) | c_ratio));
901+
ret = video_write_cci_reg(&cfg->i2c, GC2145_REG_SUBSAMPLE, ((r_ratio << 4) | c_ratio));
988902
if (ret < 0) {
989903
return ret;
990904
}
991905

992-
ret = gc2145_write_reg(&cfg->i2c, GC2145_REG_SUBSAMPLE_MODE, GC2145_SUBSAMPLE_MODE_SMOOTH);
906+
ret = video_write_cci_reg(&cfg->i2c, GC2145_REG_SUBSAMPLE_MODE,
907+
GC2145_SUBSAMPLE_MODE_SMOOTH);
993908
if (ret < 0) {
994909
return ret;
995910
}
@@ -1008,21 +923,13 @@ static uint8_t gc2145_check_connection(const struct device *dev)
1008923
{
1009924
int ret;
1010925
const struct gc2145_config *cfg = dev->config;
1011-
uint8_t reg_chip_id[2];
1012-
uint16_t chip_id;
926+
uint32_t chip_id;
1013927

1014-
ret = gc2145_read_reg(&cfg->i2c, 0xf0, &reg_chip_id[0]);
928+
ret = video_read_cci_reg(&cfg->i2c, GC2145_REG_CHIP_ID, &chip_id);
1015929
if (ret < 0) {
1016930
return ret;
1017931
}
1018932

1019-
ret = gc2145_read_reg(&cfg->i2c, 0xf1, &reg_chip_id[1]);
1020-
if (ret < 0) {
1021-
return ret;
1022-
}
1023-
1024-
chip_id = reg_chip_id[0] << 8 | reg_chip_id[1];
1025-
1026933
if (chip_id != 0x2145 && chip_id != 0x2155) {
1027934
LOG_WRN("Unexpected GC2145 chip ID: 0x%04x", chip_id);
1028935
}
@@ -1089,8 +996,8 @@ static int gc2145_set_stream(const struct device *dev, bool enable)
1089996
{
1090997
const struct gc2145_config *cfg = dev->config;
1091998

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

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

0 commit comments

Comments
 (0)