diff options
author | Laurent Pinchart <laurent.pinchart@linaro.org> | 2015-04-26 15:37:50 +0300 |
---|---|---|
committer | Laurent Pinchart <laurent.pinchart@linaro.org> | 2015-04-28 21:03:12 +0300 |
commit | 7a1309e68f9473474a3b217e17c3d6c824d2d2f5 (patch) | |
tree | fe04def4ade74936920475f56e06e5c011cbdb4d | |
parent | 0a534ab244accec2202c8e5dc53f7037313a4f60 (diff) |
media: s5k8aa: Apply resolution settings programmatically
Replace the resolution register tables by a manual configuration of the
crop and format settings. This will allow dynamic configuration of the
format and crop rectangle in the future instead of being limited to a
small number of presets.
Signed-off-by: Laurent Pinchart <laurent.pinchart@linaro.org>
Acked-By: Vaibhav Hiremath <vaibhav.hiremath@linaro.org>
-rw-r--r-- | drivers/media/i2c/soc_camera/s5k8aa.c | 200 |
1 files changed, 62 insertions, 138 deletions
diff --git a/drivers/media/i2c/soc_camera/s5k8aa.c b/drivers/media/i2c/soc_camera/s5k8aa.c index 1dad8a1fff72..4fabfdd80c79 100644 --- a/drivers/media/i2c/soc_camera/s5k8aa.c +++ b/drivers/media/i2c/soc_camera/s5k8aa.c @@ -28,11 +28,14 @@ static int debug; module_param(debug, int, 0644); -/* The token to indicate array termination */ -#define S5K8AA_TERM 0xffff +#define S5K8AA_PIXEL_ARRAY_WIDTH 1280 +#define S5K8AA_PIXEL_ARRAY_HEIGHT 920 #define S5K8AA_OUT_WIDTH_DEF 640 #define S5K8AA_OUT_HEIGHT_DEF 480 +/* The token to indicate array termination */ +#define S5K8AA_TERM 0xffff + /* * H/W register Interface (0xD0000000 - 0xD0000FFF) */ @@ -70,8 +73,8 @@ struct s5k8aa { struct media_pad pad; struct v4l2_mbus_framefmt format; + struct v4l2_rect crop; u16 fmt_reg; - const struct s5k8aa_regval *res_regs; struct clk *clk; struct regulator_bulk_data supplies[3]; @@ -2636,102 +2639,6 @@ static const struct s5k8aa_regval regs_select_display[] = { /* p150 //delay 150ms */ }; -static const struct s5k8aa_regval regs_res_qcif[] = { - {0x002A, 0x01BE}, - {0x0F12, 176}, - {0x0F12, 144}, - {0x002A, 0x01AA}, - {0x0F12, 0x0001}, - {S5K8AA_TERM, 0}, -}; - -static const struct s5k8aa_regval regs_res_240x160[] = { - {0x002A, 0x01CA}, - {0x0F12, 1200}, - {0x0F12, 800}, - {0x0F12, 0x0028}, - {0x0F12, 0x0050}, - - {0x002A, 0x01BE}, - {0x0F12, 240}, - {0x0F12, 160}, - {0x002A, 0x01AA}, - {0x0F12, 0x0001}, - {S5K8AA_TERM, 0}, -}; - -static const struct s5k8aa_regval regs_res_qvga[] = { - {0x002A, 0x01BE}, - {0x0F12, 320}, - {0x0F12, 240}, - {0x002A, 0x01AA}, - {0x0F12, 0x0001}, - {S5K8AA_TERM, 0}, -}; - -static const struct s5k8aa_regval regs_res_cif[] = { - {0x002A, 0x01BE}, - {0x0F12, 352}, - {0x0F12, 288}, - {0x002A, 0x01AA}, - {0x0F12, 0x0001}, - {S5K8AA_TERM, 0}, -}; - -static const struct s5k8aa_regval regs_res_vga[] = { - {0x002A, 0x01BE}, - {0x0F12, 640}, - {0x0F12, 480}, - {0x002A, 0x01AA}, - {0x0F12, 0x0001}, - {S5K8AA_TERM, 0}, -}; - -static const struct s5k8aa_regval regs_res_720x480[] = { - {0x002A, 0x01CA}, - {0x0F12, 720}, - {0x0F12, 480}, - {0x0F12, 0x0118}, - {0x0F12, 0x00F0}, - - {0x002A, 0x01BE}, - {0x0F12, 720}, - {0x0F12, 480}, - {0x002A, 0x01AA}, - {0x0F12, 0x0001}, - {S5K8AA_TERM, 0}, -}; - -static const struct s5k8aa_regval regs_res_wvga[] = { - {0x002A, 0x01CA}, - {0x0F12, 800}, - {0x0F12, 480}, - {0x0F12, 0x00F0}, - {0x0F12, 0x00F0}, - - {0x002A, 0x01BE}, - {0x0F12, 800}, - {0x0F12, 480}, - {0x002A, 0x01AA}, - {0x0F12, 0x0001}, - {S5K8AA_TERM, 0}, -}; - -static const struct s5k8aa_regval regs_res_720p[] = { - {0x002A, 0x01CA}, - {0x0F12, 1280}, - {0x0F12, 720}, - {0x0F12, 0x0000}, - {0x0F12, 0x0078}, - - {0x002A, 0x01BE}, - {0x0F12, 1280}, - {0x0F12, 720}, - {0x002A, 0x01AA}, - {0x0F12, 0x0001}, - {S5K8AA_TERM, 0}, -}; - /* The next two tables must be kept in sync. */ static const struct v4l2_frmsize_discrete s5k8aa_resolutions[] = { { 176, 144 }, /* QCIF */ @@ -2744,15 +2651,15 @@ static const struct v4l2_frmsize_discrete s5k8aa_resolutions[] = { { 1280, 720 }, /* 720P */ }; -static const struct s5k8aa_regval *s5k8aa_res_regs[] = { - regs_res_qcif, - regs_res_240x160, - regs_res_qvga, - regs_res_cif, - regs_res_vga, - regs_res_720x480, - regs_res_wvga, - regs_res_720p, +static const struct v4l2_rect s5k8aa_crops[] = { + { 0, 0, 1280, 920 }, /* QCIF */ + { 40, 80, 1200, 800 }, /* 240 x 160 */ + { 0, 0, 1280, 920 }, /* QVGA */ + { 0, 0, 1280, 920 }, /* CIF */ + { 0, 0, 1280, 920 }, /* VGA */ + { 280, 240, 720, 480 }, /* 720 x 480 */ + { 240, 240, 800, 480 }, /* WVGA */ + { 0, 120, 1280, 720 }, /* 720P */ }; static const struct s5k8aa_datafmt s5k8aa_colour_fmts[] = { @@ -2935,36 +2842,53 @@ static int s5k8aa_s_register(struct v4l2_subdev *sd, static int s5k8aa_s_stream(struct v4l2_subdev *sd, int enable) { struct s5k8aa *s5k8aa = to_s5k8aa(sd); - int ret = 0; + const struct v4l2_mbus_framefmt *format = &s5k8aa->format; + const struct v4l2_rect *crop = &s5k8aa->crop; + struct i2c_client *c = s5k8aa->client; + int ret; + + if (!enable) + return s5k8aa_write_raw_array(sd, regs_stop_stream); + + msleep(150); + ret = s5k8aa_write_raw_array(sd, regs_start_setting); + msleep(20); + ret |= s5k8aa_write_raw_array(sd, regs_trap_patch); + ret |= s5k8aa_write_raw_array(sd, regs_stop_stream); + ret |= s5k8aa_write_raw_array(sd, regs_analog_setting); + ret |= s5k8aa_write_raw_array(sd, regs_otp_control); + ret |= s5k8aa_write_raw_array(sd, regs_gas_setting); + ret |= s5k8aa_write_raw_array(sd, regs_analog_setting2); + ret |= s5k8aa_write_raw_array(sd, regs_awb_basic_setting); + ret |= s5k8aa_write_raw_array(sd, regs_clk_setting); + ret |= s5k8aa_write_raw_array(sd, regs_flicker_detection); + ret |= s5k8aa_write_raw_array(sd, regs_ae_setting); + ret |= s5k8aa_write_raw_array(sd, regs_ae_weight); + ret |= s5k8aa_write_raw_array(sd, regs_ccm_setting); + ret |= s5k8aa_write_raw_array(sd, regs_gamma_setting); + ret |= s5k8aa_write_raw_array(sd, regs_afit_setting); + ret |= s5k8aa_write_raw_array(sd, regs_display_setting); + + /* Format */ + ret |= s5k8aa_write(c, 0x01c4, s5k8aa->fmt_reg); + + /* Crop */ + ret |= s5k8aa_i2c_write(c, REG_CMDWR_ADDRL, 0x01ca); + ret |= s5k8aa_i2c_write(c, REG_CMDBUF0_ADDR, crop->width); + ret |= s5k8aa_i2c_write(c, REG_CMDBUF0_ADDR, crop->height); + ret |= s5k8aa_i2c_write(c, REG_CMDBUF0_ADDR, crop->left); + ret |= s5k8aa_i2c_write(c, REG_CMDBUF0_ADDR, crop->top); + + /* Output resolution */ + ret |= s5k8aa_i2c_write(c, REG_CMDWR_ADDRL, 0x01be); + ret |= s5k8aa_i2c_write(c, REG_CMDBUF0_ADDR, format->width); + ret |= s5k8aa_i2c_write(c, REG_CMDBUF0_ADDR, format->height); + + ret |= s5k8aa_write(c, 0x01aa, 0x0001); + + ret |= s5k8aa_write_raw_array(sd, regs_start_stream); + ret |= s5k8aa_write_raw_array(sd, regs_select_display); - if (enable) { - msleep(150); - ret = s5k8aa_write_raw_array(sd, regs_start_setting); - msleep(20); - ret |= s5k8aa_write_raw_array(sd, regs_trap_patch); - ret |= s5k8aa_write_raw_array(sd, regs_stop_stream); - ret |= s5k8aa_write_raw_array(sd, regs_analog_setting); - ret |= s5k8aa_write_raw_array(sd, regs_otp_control); - ret |= s5k8aa_write_raw_array(sd, regs_gas_setting); - ret |= s5k8aa_write_raw_array(sd, regs_analog_setting2); - ret |= s5k8aa_write_raw_array(sd, regs_awb_basic_setting); - ret |= s5k8aa_write_raw_array(sd, regs_clk_setting); - ret |= s5k8aa_write_raw_array(sd, regs_flicker_detection); - ret |= s5k8aa_write_raw_array(sd, regs_ae_setting); - ret |= s5k8aa_write_raw_array(sd, regs_ae_weight); - ret |= s5k8aa_write_raw_array(sd, regs_ccm_setting); - ret |= s5k8aa_write_raw_array(sd, regs_gamma_setting); - ret |= s5k8aa_write_raw_array(sd, regs_afit_setting); - ret |= s5k8aa_write_raw_array(sd, regs_display_setting); - ret |= s5k8aa_write(s5k8aa->client, 0x01c4, s5k8aa->fmt_reg); - ret |= s5k8aa_write_raw_array(sd, s5k8aa->res_regs); - - ret |= s5k8aa_write_raw_array(sd, regs_start_stream); - ret |= s5k8aa_write_raw_array(sd, regs_select_display); - - } else { - ret = s5k8aa_write_raw_array(sd, regs_stop_stream); - } return ret; } @@ -3088,7 +3012,7 @@ static int s5k8aa_set_fmt(struct v4l2_subdev *sd, if (format->which == V4L2_SUBDEV_FORMAT_ACTIVE) { s5k8aa->fmt_reg = fmt_reg; - s5k8aa->res_regs = s5k8aa_res_regs[size - s5k8aa_resolutions]; + s5k8aa->crop = s5k8aa_crops[size - s5k8aa_resolutions]; } return 0; |