aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video
diff options
context:
space:
mode:
authorSakari Ailus <sakari.ailus@maxwell.research.nokia.com>2012-04-22 08:11:26 -0400
committerMauro Carvalho Chehab <mchehab@redhat.com>2012-05-20 11:45:39 -0400
commitceb9e30e9f4a892997a61f1f5a30bc5b561c9e67 (patch)
treee11eaabf3ac03008cceab8f1abf2732349c9ba64 /drivers/media/video
parent1e73eea781bc302ba7f35da89d627bd355a7814a (diff)
[media] smiapp: Quirk for sensors that only do 8-bit reads
Some sensors implement only 8-bit read functionality and fail on wider reads. Add a quirk flag for such sensors. Signed-off-by: Sakari Ailus <sakari.ailus@maxwell.research.nokia.com> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media/video')
-rw-r--r--drivers/media/video/smiapp/smiapp-quirk.h1
-rw-r--r--drivers/media/video/smiapp/smiapp-regs.c73
-rw-r--r--drivers/media/video/smiapp/smiapp-regs.h1
3 files changed, 66 insertions, 9 deletions
diff --git a/drivers/media/video/smiapp/smiapp-quirk.h b/drivers/media/video/smiapp/smiapp-quirk.h
index 7a1b3a02a7bd..de82cdf43a89 100644
--- a/drivers/media/video/smiapp/smiapp-quirk.h
+++ b/drivers/media/video/smiapp/smiapp-quirk.h
@@ -46,6 +46,7 @@ struct smiapp_quirk {
46 46
47/* op pix clock is for all lanes in total normally */ 47/* op pix clock is for all lanes in total normally */
48#define SMIAPP_QUIRK_FLAG_OP_PIX_CLOCK_PER_LANE (1 << 0) 48#define SMIAPP_QUIRK_FLAG_OP_PIX_CLOCK_PER_LANE (1 << 0)
49#define SMIAPP_QUIRK_FLAG_8BIT_READ_ONLY (1 << 1)
49 50
50struct smiapp_reg_8 { 51struct smiapp_reg_8 {
51 u16 reg; 52 u16 reg;
diff --git a/drivers/media/video/smiapp/smiapp-regs.c b/drivers/media/video/smiapp/smiapp-regs.c
index e5e5f4356dd2..9c430647b047 100644
--- a/drivers/media/video/smiapp/smiapp-regs.c
+++ b/drivers/media/video/smiapp/smiapp-regs.c
@@ -78,19 +78,15 @@ static uint32_t float_to_u32_mul_1000000(struct i2c_client *client,
78 * Read a 8/16/32-bit i2c register. The value is returned in 'val'. 78 * Read a 8/16/32-bit i2c register. The value is returned in 'val'.
79 * Returns zero if successful, or non-zero otherwise. 79 * Returns zero if successful, or non-zero otherwise.
80 */ 80 */
81int smiapp_read(struct smiapp_sensor *sensor, u32 reg, u32 *val) 81static int ____smiapp_read(struct smiapp_sensor *sensor, u16 reg,
82 u16 len, u32 *val)
82{ 83{
83 struct i2c_client *client = v4l2_get_subdevdata(&sensor->src->sd); 84 struct i2c_client *client = v4l2_get_subdevdata(&sensor->src->sd);
84 struct i2c_msg msg; 85 struct i2c_msg msg;
85 unsigned char data[4]; 86 unsigned char data[4];
86 unsigned int len = (u8)(reg >> 16);
87 u16 offset = reg; 87 u16 offset = reg;
88 int r; 88 int r;
89 89
90 if (len != SMIA_REG_8BIT && len != SMIA_REG_16BIT
91 && len != SMIA_REG_32BIT)
92 return -EINVAL;
93
94 msg.addr = client->addr; 90 msg.addr = client->addr;
95 msg.flags = 0; 91 msg.flags = 0;
96 msg.len = 2; 92 msg.len = 2;
@@ -132,9 +128,6 @@ int smiapp_read(struct smiapp_sensor *sensor, u32 reg, u32 *val)
132 BUG(); 128 BUG();
133 } 129 }
134 130
135 if (reg & SMIA_REG_FLAG_FLOAT)
136 *val = float_to_u32_mul_1000000(client, *val);
137
138 return 0; 131 return 0;
139 132
140err: 133err:
@@ -143,6 +136,68 @@ err:
143 return r; 136 return r;
144} 137}
145 138
139/* Read a register using 8-bit access only. */
140static int ____smiapp_read_8only(struct smiapp_sensor *sensor, u16 reg,
141 u16 len, u32 *val)
142{
143 unsigned int i;
144 int rval;
145
146 *val = 0;
147
148 for (i = 0; i < len; i++) {
149 u32 val8;
150
151 rval = ____smiapp_read(sensor, reg + i, 1, &val8);
152 if (rval < 0)
153 return rval;
154 *val |= val8 << ((len - i - 1) << 3);
155 }
156
157 return 0;
158}
159
160/*
161 * Read a 8/16/32-bit i2c register. The value is returned in 'val'.
162 * Returns zero if successful, or non-zero otherwise.
163 */
164static int __smiapp_read(struct smiapp_sensor *sensor, u32 reg, u32 *val,
165 bool only8)
166{
167 struct i2c_client *client = v4l2_get_subdevdata(&sensor->src->sd);
168 unsigned int len = (u8)(reg >> 16);
169 int rval;
170
171 if (len != SMIA_REG_8BIT && len != SMIA_REG_16BIT
172 && len != SMIA_REG_32BIT)
173 return -EINVAL;
174
175 if (len == SMIA_REG_8BIT && !only8)
176 rval = ____smiapp_read(sensor, (u16)reg, len, val);
177 else
178 rval = ____smiapp_read_8only(sensor, (u16)reg, len, val);
179 if (rval < 0)
180 return rval;
181
182 if (reg & SMIA_REG_FLAG_FLOAT)
183 *val = float_to_u32_mul_1000000(client, *val);
184
185 return 0;
186}
187
188int smiapp_read(struct smiapp_sensor *sensor, u32 reg, u32 *val)
189{
190 return __smiapp_read(
191 sensor, reg, val,
192 smiapp_needs_quirk(sensor,
193 SMIAPP_QUIRK_FLAG_8BIT_READ_ONLY));
194}
195
196int smiapp_read_8only(struct smiapp_sensor *sensor, u32 reg, u32 *val)
197{
198 return __smiapp_read(sensor, reg, val, true);
199}
200
146/* 201/*
147 * Write to a 8/16-bit register. 202 * Write to a 8/16-bit register.
148 * Returns zero if successful, or non-zero otherwise. 203 * Returns zero if successful, or non-zero otherwise.
diff --git a/drivers/media/video/smiapp/smiapp-regs.h b/drivers/media/video/smiapp/smiapp-regs.h
index 1edfd206fb76..7f9013b47971 100644
--- a/drivers/media/video/smiapp/smiapp-regs.h
+++ b/drivers/media/video/smiapp/smiapp-regs.h
@@ -43,6 +43,7 @@ struct smia_reg {
43struct smiapp_sensor; 43struct smiapp_sensor;
44 44
45int smiapp_read(struct smiapp_sensor *sensor, u32 reg, u32 *val); 45int smiapp_read(struct smiapp_sensor *sensor, u32 reg, u32 *val);
46int smiapp_read_8only(struct smiapp_sensor *sensor, u32 reg, u32 *val);
46int smiapp_write(struct smiapp_sensor *sensor, u32 reg, u32 val); 47int smiapp_write(struct smiapp_sensor *sensor, u32 reg, u32 val);
47 48
48#endif 49#endif