Skip to content

Commit

Permalink
drivers: video: gc2145: Add support for YUV format.
Browse files Browse the repository at this point in the history
Can be used to get a fast grayscale image.

Signed-off-by: Ibrahim Abdalkader <i.abdalkader@gmail.com>
  • Loading branch information
iabdalkader committed Jan 24, 2025
1 parent ddff91f commit 029338a
Showing 1 changed file with 37 additions and 42 deletions.
79 changes: 37 additions & 42 deletions drivers/video/gc2145.c
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ LOG_MODULE_REGISTER(video_gc2145, CONFIG_VIDEO_LOG_LEVEL);
#define GC2145_REG_AMODE1_DEF 0x14
#define GC2145_REG_OUTPUT_FMT 0x84
#define GC2145_REG_OUTPUT_FMT_RGB565 0x06
#define GC2145_REG_OUTPUT_FMT_YCBYCR 0x02
#define GC2145_REG_SYNC_MODE 0x86
#define GC2145_REG_SYNC_MODE_DEF 0x23
#define GC2145_REG_SYNC_MODE_COL_SWITCH 0x10
Expand Down Expand Up @@ -699,18 +700,22 @@ struct gc2145_data {
.height_min = height, .height_max = height, .width_step = 0, .height_step = 0, \
}

enum resolutions {
QVGA_RESOLUTION = 0,
VGA_RESOLUTION,
UXGA_RESOLUTION,
RESOLUTIONS_MAX,
};
#define RESOLUTION_QVGA_WIDTH 320
#define RESOLUTION_QVGA_HEIGHT 240

#define RESOLUTION_VGA_WIDTH 640
#define RESOLUTION_VGA_HEIGHT 480

#define RESOLUTION_UXGA_WIDTH 1600
#define RESOLUTION_UXGA_HEIGHT 1200

static const struct video_format_cap fmts[] = {
[QVGA_RESOLUTION] = GC2145_VIDEO_FORMAT_CAP(320, 240, VIDEO_PIX_FMT_RGB565), /* QVGA */
[VGA_RESOLUTION] = GC2145_VIDEO_FORMAT_CAP(640, 480, VIDEO_PIX_FMT_RGB565), /* VGA */
[UXGA_RESOLUTION] = GC2145_VIDEO_FORMAT_CAP(1600, 1200, VIDEO_PIX_FMT_RGB565), /* UXGA */
[RESOLUTIONS_MAX] = {0},
GC2145_VIDEO_FORMAT_CAP(RESOLUTION_QVGA_WIDTH, RESOLUTION_QVGA_HEIGHT, VIDEO_PIX_FMT_RGB565),

Check warning on line 713 in drivers/video/gc2145.c

View workflow job for this annotation

GitHub Actions / Run compliance checks on patch series (PR)

LONG_LINE

drivers/video/gc2145.c:713 line length of 101 exceeds 100 columns
GC2145_VIDEO_FORMAT_CAP(RESOLUTION_VGA_WIDTH, RESOLUTION_VGA_HEIGHT, VIDEO_PIX_FMT_RGB565),
GC2145_VIDEO_FORMAT_CAP(RESOLUTION_UXGA_WIDTH, RESOLUTION_UXGA_HEIGHT, VIDEO_PIX_FMT_RGB565),

Check warning on line 715 in drivers/video/gc2145.c

View workflow job for this annotation

GitHub Actions / Run compliance checks on patch series (PR)

LONG_LINE

drivers/video/gc2145.c:715 line length of 101 exceeds 100 columns
GC2145_VIDEO_FORMAT_CAP(RESOLUTION_QVGA_WIDTH, RESOLUTION_QVGA_HEIGHT, VIDEO_PIX_FMT_YUYV),
GC2145_VIDEO_FORMAT_CAP(RESOLUTION_VGA_WIDTH, RESOLUTION_VGA_HEIGHT, VIDEO_PIX_FMT_YUYV),
GC2145_VIDEO_FORMAT_CAP(RESOLUTION_UXGA_WIDTH, RESOLUTION_UXGA_HEIGHT, VIDEO_PIX_FMT_YUYV),
};

static int gc2145_write_reg(const struct i2c_dt_spec *spec, uint8_t reg_addr, uint8_t value)
Expand Down Expand Up @@ -893,13 +898,17 @@ static int gc2145_set_output_format(const struct device *dev, int output_format)
return ret;
}

if (output_format != VIDEO_PIX_FMT_RGB565) {
/* Map format to sensor format */
if (output_format == VIDEO_PIX_FMT_RGB565) {

Check warning on line 902 in drivers/video/gc2145.c

View workflow job for this annotation

GitHub Actions / Run compliance checks on patch series (PR)

LEADING_SPACE

drivers/video/gc2145.c:902 please, no spaces at the start of a line
output_format = GC2145_REG_OUTPUT_FMT_RGB565;

Check failure on line 903 in drivers/video/gc2145.c

View workflow job for this annotation

GitHub Actions / Run compliance checks on patch series (PR)

CODE_INDENT

drivers/video/gc2145.c:903 code indent should use tabs where possible

Check warning on line 903 in drivers/video/gc2145.c

View workflow job for this annotation

GitHub Actions / Run compliance checks on patch series (PR)

LEADING_SPACE

drivers/video/gc2145.c:903 please, no spaces at the start of a line
} else if (output_format == VIDEO_PIX_FMT_YUYV) {

Check warning on line 904 in drivers/video/gc2145.c

View workflow job for this annotation

GitHub Actions / Run compliance checks on patch series (PR)

LEADING_SPACE

drivers/video/gc2145.c:904 please, no spaces at the start of a line
output_format = GC2145_REG_OUTPUT_FMT_YCBYCR;

Check failure on line 905 in drivers/video/gc2145.c

View workflow job for this annotation

GitHub Actions / Run compliance checks on patch series (PR)

CODE_INDENT

drivers/video/gc2145.c:905 code indent should use tabs where possible

Check warning on line 905 in drivers/video/gc2145.c

View workflow job for this annotation

GitHub Actions / Run compliance checks on patch series (PR)

LEADING_SPACE

drivers/video/gc2145.c:905 please, no spaces at the start of a line
} else {

Check warning on line 906 in drivers/video/gc2145.c

View workflow job for this annotation

GitHub Actions / Run compliance checks on patch series (PR)

LEADING_SPACE

drivers/video/gc2145.c:906 please, no spaces at the start of a line

Check warning on line 906 in drivers/video/gc2145.c

View workflow job for this annotation

GitHub Actions / Run compliance checks on patch series (PR)

SUSPECT_CODE_INDENT

drivers/video/gc2145.c:906 suspect code indent for conditional statements (4, 16)
LOG_ERR("Image format not supported");
return -ENOTSUP;
}

/* Disable JPEG compression and set output to RGB565 */
ret = gc2145_write_reg(&cfg->i2c, GC2145_REG_OUTPUT_FMT, GC2145_REG_OUTPUT_FMT_RGB565);
ret = gc2145_write_reg(&cfg->i2c, GC2145_REG_OUTPUT_FMT, output_format);

Check warning on line 911 in drivers/video/gc2145.c

View workflow job for this annotation

GitHub Actions / Run compliance checks on patch series (PR)

LEADING_SPACE

drivers/video/gc2145.c:911 please, no spaces at the start of a line
if (ret < 0) {
return ret;
}
Expand All @@ -909,13 +918,11 @@ static int gc2145_set_output_format(const struct device *dev, int output_format)
return 0;
}

static int gc2145_set_resolution(const struct device *dev, enum resolutions res)
static int gc2145_set_resolution(const struct device *dev, uint32_t w, uint32_t h)
{
int ret;
const struct gc2145_config *cfg = dev->config;

uint16_t w;
uint16_t h;
uint16_t win_w;
uint16_t win_h;
uint16_t c_ratio;
Expand All @@ -925,29 +932,22 @@ static int gc2145_set_resolution(const struct device *dev, enum resolutions res)
uint16_t win_x;
uint16_t win_y;

if (res >= RESOLUTIONS_MAX) {
return -EIO;
}

w = fmts[res].width_min;
h = fmts[res].height_min;

/* Add the subsampling factor depending on resolution */
switch (res) {
case QVGA_RESOLUTION:
switch (w) {
case RESOLUTION_QVGA_WIDTH:
c_ratio = 3;
r_ratio = 3;
break;
case VGA_RESOLUTION:
case RESOLUTION_VGA_WIDTH:
c_ratio = 2;
r_ratio = 2;
break;
case UXGA_RESOLUTION:
case RESOLUTION_UXGA_WIDTH:
c_ratio = 1;
r_ratio = 1;
break;
default:
LOG_ERR("Unsupported resolution %d", res);
LOG_ERR("Unsupported resolution %d %d", w, h);
return -EIO;
};

Expand Down Expand Up @@ -1027,29 +1027,23 @@ static int gc2145_set_fmt(const struct device *dev, enum video_endpoint_id ep,
struct video_format *fmt)
{
struct gc2145_data *drv_data = dev->data;
enum resolutions res = RESOLUTIONS_MAX;
size_t res = ARRAY_SIZE(fmts);
int ret;

/* We only support RGB565 formats */
if (fmt->pixelformat != VIDEO_PIX_FMT_RGB565) {
LOG_ERR("gc2145 camera supports only RGB565");
return -ENOTSUP;
}

if (memcmp(&drv_data->fmt, fmt, sizeof(drv_data->fmt)) == 0) {
/* nothing to do */
return 0;
}

/* Check if camera is capable of handling given format */
for (int i = 0; i < RESOLUTIONS_MAX; i++) {
for (int i = 0; i < ARRAY_SIZE(fmts); i++) {
if (fmts[i].width_min == fmt->width && fmts[i].height_min == fmt->height &&
fmts[i].pixelformat == fmt->pixelformat) {
res = (enum resolutions)i;
res = i;
break;
}
}
if (res == RESOLUTIONS_MAX) {
if (res == ARRAY_SIZE(fmts)) {
LOG_ERR("Image format not supported");
return -ENOTSUP;
}
Expand All @@ -1064,7 +1058,8 @@ static int gc2145_set_fmt(const struct device *dev, enum video_endpoint_id ep,
}

/* Set window size */
ret = gc2145_set_resolution(dev, res);
ret = gc2145_set_resolution(dev, fmt->width, fmt->height);

if (ret < 0) {
LOG_ERR("Failed to set the resolution");
return ret;
Expand Down Expand Up @@ -1161,9 +1156,9 @@ static int gc2145_init(const struct device *dev)

/* set default/init format QVGA RGB565 */
fmt.pixelformat = VIDEO_PIX_FMT_RGB565;
fmt.width = fmts[QVGA_RESOLUTION].width_min;
fmt.height = fmts[QVGA_RESOLUTION].height_min;
fmt.pitch = fmts[QVGA_RESOLUTION].width_min * 2;
fmt.width = RESOLUTION_QVGA_WIDTH;
fmt.height = RESOLUTION_QVGA_HEIGHT;
fmt.pitch = RESOLUTION_QVGA_WIDTH * 2;

ret = gc2145_set_fmt(dev, VIDEO_EP_OUT, &fmt);
if (ret) {
Expand Down

0 comments on commit 029338a

Please sign in to comment.