aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLaurent Pinchart <laurent.pinchart@linaro.org>2015-04-26 15:37:50 +0300
committerLaurent Pinchart <laurent.pinchart@linaro.org>2015-04-28 21:03:12 +0300
commit7a1309e68f9473474a3b217e17c3d6c824d2d2f5 (patch)
treefe04def4ade74936920475f56e06e5c011cbdb4d
parent0a534ab244accec2202c8e5dc53f7037313a4f60 (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.c200
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;