aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video/tegra/tps61050.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media/video/tegra/tps61050.c')
-rw-r--r--drivers/media/video/tegra/tps61050.c991
1 files changed, 991 insertions, 0 deletions
diff --git a/drivers/media/video/tegra/tps61050.c b/drivers/media/video/tegra/tps61050.c
new file mode 100644
index 00000000000..def353ca9c1
--- /dev/null
+++ b/drivers/media/video/tegra/tps61050.c
@@ -0,0 +1,991 @@
1/*
2 * tps61050.c - tps61050 flash/torch kernel driver
3 *
4 * Copyright (C) 2011 NVIDIA Corporation.
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
18 * 02111-1307, USA
19 */
20
21/* Implementation
22 * --------------
23 * The board level details about the device need to be provided in the board
24 * file with the tps61050_platform_data structure.
25 * Standard among NVC kernel drivers in this structure is:
26 * .cfg = Use the NVC_CFG_ defines that are in nvc_torch.h.
27 * Descriptions of the configuration options are with the defines.
28 * This value is typically 0.
29 * .num = The number of the instance of the device. This should start at 1 and
30 * and increment for each device on the board. This number will be
31 * appended to the MISC driver name, Example: /dev/tps61050.1
32 * .sync = If there is a need to synchronize two devices, then this value is
33 * the number of the device instance this device is allowed to sync to.
34 * This is typically used for stereo applications.
35 * .dev_name = The MISC driver name the device registers as. If not used,
36 * then the part number of the device is used for the driver name.
37 * If using the NVC user driver then use the name found in this
38 * driver under _default_pdata.
39 *
40 * The following is specific to NVC kernel flash/torch drivers:
41 * .pinstate = a pointer to the nvc_torch_pin_state structure. This
42 * structure gives the details of which VI GPIO to use to trigger
43 * the flash. The mask tells which pin and the values is the
44 * level. For example, if VI GPIO pin 6 is used, then
45 * .mask = 0x0040
46 * .values = 0x0040
47 * If VI GPIO pin 0 is used, then
48 * .mask = 0x0001
49 * .values = 0x0001
50 * This is typically just one pin but there is some legacy
51 * here that insinuates more than one pin can be used.
52 * When the flash level is set, then the driver will return the
53 * value in values. When the flash level is off, the driver will
54 * return 0 for the values to deassert the signal.
55 * If a VI GPIO is not used, then the mask and values must be set
56 * to 0. The flash may then be triggered via I2C instead.
57 * However, a VI GPIO is strongly encouraged since it allows
58 * tighter timing with the picture taken as well as reduced power
59 * by asserting the trigger signal for only when needed.
60 * .max_amp_torch = Is the maximum torch value allowed. The value is 0 to
61 * _MAX_TORCH_LEVEL. This is to allow a limit to the amount
62 * of amps used. If left blank then _MAX_TORCH_LEVEL will be
63 * used.
64 * .max_amp_flash = Is the maximum flash value allowed. The value is 0 to
65 * _MAX_FLASH_LEVEL. This is to allow a limit to the amount
66 * of amps used. If left blank then _MAX_FLASH_LEVEL will be
67 * used.
68 *
69 * The following is specific to only this NVC kernel flash/torch driver:
70 * N/A
71 *
72 * Power Requirements
73 * The board power file must contain the following labels for the power
74 * regulator(s) of this device:
75 * "vdd_i2c" = the power regulator for the I2C power.
76 * Note that this device is typically connected directly to the battery rail
77 * and does not need a source power regulator (vdd).
78 *
79 * The above values should be all that is needed to use the device with this
80 * driver. Modifications of this driver should not be needed.
81 */
82
83
84#include <linux/fs.h>
85#include <linux/i2c.h>
86#include <linux/miscdevice.h>
87#include <linux/slab.h>
88#include <linux/delay.h>
89#include <linux/uaccess.h>
90#include <linux/list.h>
91#include <linux/regulator/consumer.h>
92#include <media/nvc.h>
93#include <media/tps61050.h>
94
95#define TPS61050_REG0 0x00
96#define TPS61050_REG1 0x01
97#define TPS61050_REG2 0x02
98#define TPS61050_REG3 0x03
99#define tps61050_flash_cap_size (sizeof(tps61050_flash_cap.numberoflevels) \
100 + (sizeof(tps61050_flash_cap.levels[0]) \
101 * (TPS61050_MAX_FLASH_LEVEL + 1)))
102#define tps61050_torch_cap_size (sizeof(tps61050_torch_cap.numberoflevels) \
103 + (sizeof(tps61050_torch_cap.guidenum[0]) \
104 * (TPS61050_MAX_TORCH_LEVEL + 1)))
105
106
107static struct nvc_torch_flash_capabilities tps61050_flash_cap = {
108 TPS61050_MAX_FLASH_LEVEL + 1,
109 {
110 { 0, 0xFFFFFFFF, 0 },
111 { 150, 558, 2 },
112 { 200, 558, 2 },
113 { 300, 558, 2 },
114 { 400, 558, 2 },
115 { 500, 558, 2 },
116 { 700, 558, 2 },
117 { 900, 558, 2 },
118 { 900, 558, 2 }
119 }
120};
121
122static struct nvc_torch_torch_capabilities tps61050_torch_cap = {
123 TPS61050_MAX_TORCH_LEVEL + 1,
124 {
125 0,
126 50,
127 75,
128 100,
129 150,
130 200,
131 491,
132 491
133 }
134};
135
136struct tps61050_info {
137 atomic_t in_use;
138 struct i2c_client *i2c_client;
139 struct tps61050_platform_data *pdata;
140 struct miscdevice miscdev;
141 struct list_head list;
142 int pwr_api;
143 int pwr_dev;
144 struct nvc_regulator vreg_i2c;
145 u8 s_mode;
146 struct tps61050_info *s_info;
147};
148
149static struct nvc_torch_pin_state tps61050_default_pinstate = {
150 .mask = 0x0000,
151 .values = 0x0000,
152};
153
154static struct tps61050_platform_data tps61050_default_pdata = {
155 .cfg = 0,
156 .num = 0,
157 .sync = 0,
158 .dev_name = "torch",
159 .pinstate = &tps61050_default_pinstate,
160 .max_amp_torch = TPS61050_MAX_TORCH_LEVEL,
161 .max_amp_flash = TPS61050_MAX_FLASH_LEVEL,
162};
163
164static LIST_HEAD(tps61050_info_list);
165static DEFINE_SPINLOCK(tps61050_spinlock);
166
167
168static int tps61050_i2c_rd(struct tps61050_info *info, u8 reg, u8 *val)
169{
170 struct i2c_msg msg[2];
171 u8 buf[2];
172
173 buf[0] = reg;
174 msg[0].addr = info->i2c_client->addr;
175 msg[0].flags = 0;
176 msg[0].len = 1;
177 msg[0].buf = &buf[0];
178 msg[1].addr = info->i2c_client->addr;
179 msg[1].flags = I2C_M_RD;
180 msg[1].len = 1;
181 msg[1].buf = &buf[1];
182 *val = 0;
183 if (i2c_transfer(info->i2c_client->adapter, msg, 2) != 2)
184 return -EIO;
185
186 *val = buf[1];
187 return 0;
188}
189
190static int tps61050_i2c_wr(struct tps61050_info *info, u8 reg, u8 val)
191{
192 struct i2c_msg msg;
193 u8 buf[2];
194
195 buf[0] = reg;
196 buf[1] = val;
197 msg.addr = info->i2c_client->addr;
198 msg.flags = 0;
199 msg.len = 2;
200 msg.buf = &buf[0];
201 if (i2c_transfer(info->i2c_client->adapter, &msg, 1) != 1)
202 return -EIO;
203
204 return 0;
205}
206
207static void tps61050_pm_regulator_put(struct nvc_regulator *sreg)
208{
209 regulator_put(sreg->vreg);
210 sreg->vreg = NULL;
211}
212
213static int tps61050_pm_regulator_get(struct tps61050_info *info,
214 struct nvc_regulator *sreg,
215 char vreg_name[])
216{
217 int err = 0;
218
219 sreg->vreg_flag = 0;
220 sreg->vreg = regulator_get(&info->i2c_client->dev, vreg_name);
221 if (IS_ERR_OR_NULL(sreg->vreg)) {
222 dev_err(&info->i2c_client->dev,
223 "%s err for regulator: %s err: %d\n",
224 __func__, vreg_name, (int)sreg->vreg);
225 err = PTR_ERR(sreg->vreg);
226 sreg->vreg = NULL;
227 } else {
228 sreg->vreg_name = vreg_name;
229 dev_dbg(&info->i2c_client->dev,
230 "%s vreg_name: %s\n",
231 __func__, sreg->vreg_name);
232 }
233 return err;
234}
235
236static int tps61050_pm_regulator_en(struct tps61050_info *info,
237 struct nvc_regulator *sreg)
238{
239 int err = 0;
240
241 if (!sreg->vreg_flag && (sreg->vreg != NULL)) {
242 err = regulator_enable(sreg->vreg);
243 if (!err) {
244 dev_dbg(&info->i2c_client->dev,
245 "%s vreg_name: %s\n",
246 __func__, sreg->vreg_name);
247 sreg->vreg_flag = 1;
248 err = 1; /* flag regulator state change */
249 mdelay(5); /* device powerup delay */
250 } else {
251 dev_err(&info->i2c_client->dev,
252 "%s err, regulator: %s\n",
253 __func__, sreg->vreg_name);
254 }
255 }
256 return err;
257}
258
259static int tps61050_pm_regulator_dis(struct tps61050_info *info,
260 struct nvc_regulator *sreg)
261{
262 int err = 0;
263
264 if (sreg->vreg_flag && (sreg->vreg != NULL)) {
265 err = regulator_disable(sreg->vreg);
266 if (!err)
267 dev_dbg(&info->i2c_client->dev,
268 "%s vreg_name: %s\n",
269 __func__, sreg->vreg_name);
270 else
271 dev_err(&info->i2c_client->dev,
272 "%s err, regulator: %s\n",
273 __func__, sreg->vreg_name);
274 }
275 sreg->vreg_flag = 0;
276 return err;
277}
278
279static int tps61050_pm_wr(struct tps61050_info *info, int pwr)
280{
281 int err = 0;
282 u8 reg;
283
284 if (pwr == info->pwr_dev)
285 return 0;
286
287 switch (pwr) {
288 case NVC_PWR_OFF:
289 if ((info->pdata->cfg & NVC_CFG_OFF2STDBY) ||
290 (info->pdata->cfg & NVC_CFG_BOOT_INIT)) {
291 pwr = NVC_PWR_STDBY;
292 } else {
293 err = tps61050_pm_regulator_en(info, &info->vreg_i2c);
294 err |= tps61050_i2c_wr(info, TPS61050_REG0, 0x00);
295 err |= tps61050_i2c_wr(info, TPS61050_REG1, 0x00);
296 err |= tps61050_pm_regulator_dis(info, &info->vreg_i2c);
297 break;
298 }
299 case NVC_PWR_STDBY_OFF:
300 if ((info->pdata->cfg & NVC_CFG_OFF2STDBY) ||
301 (info->pdata->cfg & NVC_CFG_BOOT_INIT)) {
302 pwr = NVC_PWR_STDBY;
303 } else {
304 err = tps61050_pm_regulator_en(info, &info->vreg_i2c);
305 err |= tps61050_i2c_wr(info, TPS61050_REG0, 0x00);
306 err |= tps61050_i2c_wr(info, TPS61050_REG1, 0x00);
307 break;
308 }
309 case NVC_PWR_STDBY:
310 err = tps61050_pm_regulator_en(info, &info->vreg_i2c);
311 err |= tps61050_i2c_rd(info, TPS61050_REG0, &reg);
312 reg &= 0x3F; /* 7:6 = mode */
313 err |= tps61050_i2c_wr(info, TPS61050_REG0, reg);
314 break;
315
316 case NVC_PWR_COMM:
317 case NVC_PWR_ON:
318 err = tps61050_pm_regulator_en(info, &info->vreg_i2c);
319 break;
320
321 default:
322 err = -EINVAL;
323 break;
324 }
325
326 if (err < 0) {
327 dev_err(&info->i2c_client->dev, "%s error\n", __func__);
328 pwr = NVC_PWR_ERR;
329 }
330 info->pwr_dev = pwr;
331 if (err > 0)
332 return 0;
333
334 return err;
335}
336
337static int tps61050_pm_wr_s(struct tps61050_info *info, int pwr)
338{
339 int err1 = 0;
340 int err2 = 0;
341
342 if ((info->s_mode == NVC_SYNC_OFF) ||
343 (info->s_mode == NVC_SYNC_MASTER) ||
344 (info->s_mode == NVC_SYNC_STEREO))
345 err1 = tps61050_pm_wr(info, pwr);
346 if ((info->s_mode == NVC_SYNC_SLAVE) ||
347 (info->s_mode == NVC_SYNC_STEREO))
348 err2 = tps61050_pm_wr(info->s_info, pwr);
349 return err1 | err2;
350}
351
352static int tps61050_pm_api_wr(struct tps61050_info *info, int pwr)
353{
354 int err = 0;
355
356 if (!pwr || (pwr > NVC_PWR_ON))
357 return 0;
358
359 if (pwr > info->pwr_dev)
360 err = tps61050_pm_wr_s(info, pwr);
361 if (!err)
362 info->pwr_api = pwr;
363 else
364 info->pwr_api = NVC_PWR_ERR;
365 if (info->pdata->cfg & NVC_CFG_NOERR)
366 return 0;
367
368 return err;
369}
370
371static int tps61050_pm_dev_wr(struct tps61050_info *info, int pwr)
372{
373 if (pwr < info->pwr_api)
374 pwr = info->pwr_api;
375 return tps61050_pm_wr(info, pwr);
376}
377
378static void tps61050_pm_exit(struct tps61050_info *info)
379{
380 tps61050_pm_wr_s(info, NVC_PWR_OFF);
381 tps61050_pm_regulator_put(&info->vreg_i2c);
382}
383
384static void tps61050_pm_init(struct tps61050_info *info)
385{
386 tps61050_pm_regulator_get(info, &info->vreg_i2c, "vdd_i2c");
387}
388
389struct tps61050_reg_init {
390 u8 mask;
391 u8 val;
392};
393
394static struct tps61050_reg_init tps61050_reg_init_id[] = {
395 {0xC0, 0x00},
396 {0xC0, 0x00},
397 {0x87, 0x00},
398 {0xFF, 0xD1},
399};
400
401static int tps61050_dev_id(struct tps61050_info *info)
402{
403 u8 reg;
404 u8 i;
405 int err;
406
407 tps61050_pm_dev_wr(info, NVC_PWR_COMM);
408 /* There isn't a device ID so we just check that all the registers
409 * equal their startup defaults.
410 */
411 for (i = TPS61050_REG0; i <= TPS61050_REG3; i++) {
412 err = tps61050_i2c_rd(info, i, &reg);
413 if (err) {
414 break;
415 } else {
416 reg &= tps61050_reg_init_id[i].mask;
417 if (reg != tps61050_reg_init_id[i].val) {
418 err = -ENODEV;
419 break;
420 }
421 }
422 }
423 tps61050_pm_dev_wr(info, NVC_PWR_OFF);
424 return err;
425}
426
427static int tps61050_param_rd(struct tps61050_info *info, long arg)
428{
429 struct nvc_param params;
430 struct nvc_torch_pin_state pinstate;
431 const void *data_ptr;
432 u8 reg;
433 u32 data_size = 0;
434 int err;
435
436 if (copy_from_user(&params,
437 (const void __user *)arg,
438 sizeof(struct nvc_param))) {
439 dev_err(&info->i2c_client->dev, "%s %d copy_from_user err\n",
440 __func__, __LINE__);
441 return -EINVAL;
442 }
443
444 if (info->s_mode == NVC_SYNC_SLAVE)
445 info = info->s_info;
446 switch (params.param) {
447 case NVC_PARAM_FLASH_CAPS:
448 dev_dbg(&info->i2c_client->dev, "%s FLASH_CAPS\n", __func__);
449 data_ptr = &tps61050_flash_cap;
450 data_size = tps61050_flash_cap_size;
451 break;
452
453 case NVC_PARAM_FLASH_LEVEL:
454 tps61050_pm_dev_wr(info, NVC_PWR_COMM);
455 err = tps61050_i2c_rd(info, TPS61050_REG1, &reg);
456 tps61050_pm_dev_wr(info, NVC_PWR_OFF);
457 if (err < 0)
458 return err;
459
460 if (reg & 0x80) { /* 7:7 flash on/off */
461 reg &= 0x07; /* 2:0 flash setting */
462 reg++; /* flash setting +1 if flash on */
463 } else {
464 reg = 0; /* flash is off */
465 }
466 dev_dbg(&info->i2c_client->dev, "%s FLASH_LEVEL: %u\n",
467 __func__,
468 (unsigned)tps61050_flash_cap.levels[reg].guidenum);
469 data_ptr = &tps61050_flash_cap.levels[reg].guidenum;
470 data_size = sizeof(tps61050_flash_cap.levels[reg].guidenum);
471 break;
472
473 case NVC_PARAM_TORCH_CAPS:
474 dev_dbg(&info->i2c_client->dev, "%s TORCH_CAPS\n", __func__);
475 data_ptr = &tps61050_torch_cap;
476 data_size = tps61050_torch_cap_size;
477 break;
478
479 case NVC_PARAM_TORCH_LEVEL:
480 tps61050_pm_dev_wr(info, NVC_PWR_COMM);
481 err = tps61050_i2c_rd(info, TPS61050_REG0, &reg);
482 tps61050_pm_dev_wr(info, NVC_PWR_OFF);
483 if (err < 0)
484 return err;
485
486 reg &= 0x07;
487 dev_dbg(&info->i2c_client->dev, "%s TORCH_LEVEL: %u\n",
488 __func__,
489 (unsigned)tps61050_torch_cap.guidenum[reg]);
490 data_ptr = &tps61050_torch_cap.guidenum[reg];
491 data_size = sizeof(tps61050_torch_cap.guidenum[reg]);
492 break;
493
494 case NVC_PARAM_FLASH_PIN_STATE:
495 pinstate.mask = info->pdata->pinstate->mask;
496 tps61050_pm_dev_wr(info, NVC_PWR_COMM);
497 err = tps61050_i2c_rd(info, TPS61050_REG1, &reg);
498 tps61050_pm_dev_wr(info, NVC_PWR_OFF);
499 if (err < 0)
500 return err;
501
502 reg &= 0x80; /* 7:7=flash enable */
503 if (reg)
504 /* assert strobe */
505 pinstate.values = info->pdata->pinstate->values;
506 else
507 pinstate.values = 0; /* deassert strobe */
508 dev_dbg(&info->i2c_client->dev, "%s FLASH_PIN_STATE: %x&%x\n",
509 __func__, pinstate.mask, pinstate.values);
510 data_ptr = &pinstate;
511 data_size = sizeof(struct nvc_torch_pin_state);
512 break;
513
514 case NVC_PARAM_STEREO:
515 dev_dbg(&info->i2c_client->dev, "%s STEREO: %d\n",
516 __func__, (int)info->s_mode);
517 data_ptr = &info->s_mode;
518 data_size = sizeof(info->s_mode);
519 break;
520
521 default:
522 dev_err(&info->i2c_client->dev,
523 "%s unsupported parameter: %d\n",
524 __func__, params.param);
525 return -EINVAL;
526 }
527
528 if (params.sizeofvalue < data_size) {
529 dev_err(&info->i2c_client->dev,
530 "%s data size mismatch %d != %d\n",
531 __func__, params.sizeofvalue, data_size);
532 return -EINVAL;
533 }
534
535 if (copy_to_user((void __user *)params.p_value,
536 data_ptr,
537 data_size)) {
538 dev_err(&info->i2c_client->dev,
539 "%s copy_to_user err line %d\n",
540 __func__, __LINE__);
541 return -EFAULT;
542 }
543
544 return 0;
545}
546
547static int tps61050_param_wr_s(struct tps61050_info *info,
548 struct nvc_param *params,
549 u8 val)
550{
551 u8 reg;
552 int err = 0;
553
554 /*
555 * 7:6 flash/torch mode
556 * 0 0 = off (power save)
557 * 0 1 = torch only (torch power is 2:0 REG0 where 0 = off)
558 * 1 0 = flash and torch (flash power is 2:0 REG1 (0 is a power level))
559 * 1 1 = N/A
560 * Note that 7:6 of REG0 and REG1 are shadowed with each other.
561 * In the code below we want to turn on/off one
562 * without affecting the other.
563 */
564 switch (params->param) {
565 case NVC_PARAM_FLASH_LEVEL:
566 dev_dbg(&info->i2c_client->dev, "%s FLASH_LEVEL: %d\n",
567 __func__, val);
568 tps61050_pm_dev_wr(info, NVC_PWR_ON);
569 if (val) {
570 val--;
571 if (val > tps61050_default_pdata.max_amp_flash)
572 val = tps61050_default_pdata.max_amp_flash;
573 /* Amp limit values are in the board-sensors file. */
574 if (info->pdata->max_amp_flash &&
575 (val > info->pdata->max_amp_flash))
576 val = info->pdata->max_amp_flash;
577 val |= 0x80; /* 7:7=flash mode */
578 } else {
579 err = tps61050_i2c_rd(info, TPS61050_REG0, &reg);
580 if (reg & 0x07) /* 2:0=torch setting */
581 val = 0x40; /* 6:6 enable just torch */
582 }
583 err |= tps61050_i2c_wr(info, TPS61050_REG1, val);
584 val &= 0xC0; /* 7:6=flash/torch mode */
585 if (!val) /* turn pwr off if no flash && no pwr_api */
586 tps61050_pm_dev_wr(info, NVC_PWR_OFF);
587 return err;
588
589 case NVC_PARAM_TORCH_LEVEL:
590 dev_dbg(&info->i2c_client->dev, "%s TORCH_LEVEL: %d\n",
591 __func__, val);
592 tps61050_pm_dev_wr(info, NVC_PWR_ON);
593 err = tps61050_i2c_rd(info, TPS61050_REG1, &reg);
594 reg &= 0x80; /* 7:7=flash */
595 if (val) {
596 if (val > tps61050_default_pdata.max_amp_torch)
597 val = tps61050_default_pdata.max_amp_torch;
598 /* Amp limit values are in the board-sensors file. */
599 if (info->pdata->max_amp_torch &&
600 (val > info->pdata->max_amp_torch))
601 val = info->pdata->max_amp_torch;
602 if (!reg) /* test if flash/torch off */
603 val |= (0x40); /* 6:6=torch only mode */
604 } else {
605 val |= reg;
606 }
607 err |= tps61050_i2c_wr(info, TPS61050_REG0, val);
608 val &= 0xC0; /* 7:6=mode */
609 if (!val) /* turn pwr off if no torch && no pwr_api */
610 tps61050_pm_dev_wr(info, NVC_PWR_OFF);
611 return err;
612
613 case NVC_PARAM_FLASH_PIN_STATE:
614 dev_dbg(&info->i2c_client->dev, "%s FLASH_PIN_STATE: %d\n",
615 __func__, val);
616 if (val)
617 val = 0x08; /* 3:3=soft trigger */
618 err = tps61050_i2c_rd(info, TPS61050_REG1, &reg);
619 val |= reg;
620 err |= tps61050_i2c_wr(info, TPS61050_REG1, val);
621 return err;
622
623 default:
624 dev_err(&info->i2c_client->dev,
625 "%s unsupported parameter: %d\n",
626 __func__, params->param);
627 return -EINVAL;
628 }
629}
630
631static int tps61050_param_wr(struct tps61050_info *info, long arg)
632{
633 struct nvc_param params;
634 u8 val;
635 int err = 0;
636
637 if (copy_from_user(&params, (const void __user *)arg,
638 sizeof(struct nvc_param))) {
639 dev_err(&info->i2c_client->dev, "%s %d copy_from_user err\n",
640 __func__, __LINE__);
641 return -EINVAL;
642 }
643
644 if (copy_from_user(&val, (const void __user *)params.p_value,
645 sizeof(val))) {
646 dev_err(&info->i2c_client->dev, "%s %d copy_from_user err\n",
647 __func__, __LINE__);
648 return -EINVAL;
649 }
650
651 /* parameters independent of sync mode */
652 switch (params.param) {
653 case NVC_PARAM_STEREO:
654 dev_dbg(&info->i2c_client->dev, "%s STEREO: %d\n",
655 __func__, (int)val);
656 if (val == info->s_mode)
657 return 0;
658
659 switch (val) {
660 case NVC_SYNC_OFF:
661 info->s_mode = val;
662 if (info->s_info != NULL) {
663 info->s_info->s_mode = val;
664 tps61050_pm_wr(info->s_info, NVC_PWR_OFF);
665 }
666 break;
667
668 case NVC_SYNC_MASTER:
669 info->s_mode = val;
670 if (info->s_info != NULL)
671 info->s_info->s_mode = val;
672 break;
673
674 case NVC_SYNC_SLAVE:
675 case NVC_SYNC_STEREO:
676 if (info->s_info != NULL) {
677 /* sync power */
678 info->s_info->pwr_api = info->pwr_api;
679 err = tps61050_pm_wr(info->s_info,
680 info->pwr_dev);
681 if (!err) {
682 info->s_mode = val;
683 info->s_info->s_mode = val;
684 } else {
685 tps61050_pm_wr(info->s_info,
686 NVC_PWR_OFF);
687 err = -EIO;
688 }
689 } else {
690 err = -EINVAL;
691 }
692 break;
693
694 default:
695 err = -EINVAL;
696 }
697 if (info->pdata->cfg & NVC_CFG_NOERR)
698 return 0;
699
700 return err;
701
702 default:
703 /* parameters dependent on sync mode */
704 switch (info->s_mode) {
705 case NVC_SYNC_OFF:
706 case NVC_SYNC_MASTER:
707 return tps61050_param_wr_s(info, &params, val);
708
709 case NVC_SYNC_SLAVE:
710 return tps61050_param_wr_s(info->s_info,
711 &params,
712 val);
713
714 case NVC_SYNC_STEREO:
715 err = tps61050_param_wr_s(info, &params, val);
716 if (!(info->pdata->cfg & NVC_CFG_SYNC_I2C_MUX))
717 err |= tps61050_param_wr_s(info->s_info,
718 &params,
719 val);
720 return err;
721
722 default:
723 dev_err(&info->i2c_client->dev, "%s %d internal err\n",
724 __func__, __LINE__);
725 return -EINVAL;
726 }
727 }
728}
729
730static long tps61050_ioctl(struct file *file,
731 unsigned int cmd,
732 unsigned long arg)
733{
734 struct tps61050_info *info = file->private_data;
735 int pwr;
736
737 switch (cmd) {
738 case NVC_IOCTL_PARAM_WR:
739 return tps61050_param_wr(info, arg);
740
741 case NVC_IOCTL_PARAM_RD:
742 return tps61050_param_rd(info, arg);
743
744 case NVC_IOCTL_PWR_WR:
745 /* This is a Guaranteed Level of Service (GLOS) call */
746 pwr = (int)arg * 2;
747 dev_dbg(&info->i2c_client->dev, "%s PWR_WR: %d\n",
748 __func__, pwr);
749 return tps61050_pm_api_wr(info, pwr);
750
751 case NVC_IOCTL_PWR_RD:
752 if (info->s_mode == NVC_SYNC_SLAVE)
753 pwr = info->s_info->pwr_api / 2;
754 else
755 pwr = info->pwr_api / 2;
756 dev_dbg(&info->i2c_client->dev, "%s PWR_RD: %d\n",
757 __func__, pwr);
758 if (copy_to_user((void __user *)arg, (const void *)&pwr,
759 sizeof(pwr))) {
760 dev_err(&info->i2c_client->dev,
761 "%s copy_to_user err line %d\n",
762 __func__, __LINE__);
763 return -EFAULT;
764 }
765 return 0;
766
767 default:
768 dev_err(&info->i2c_client->dev, "%s unsupported ioctl: %x\n",
769 __func__, cmd);
770 return -EINVAL;
771 }
772}
773
774static int tps61050_sync_en(int dev1, int dev2)
775{
776 struct tps61050_info *sync1 = NULL;
777 struct tps61050_info *sync2 = NULL;
778 struct tps61050_info *pos = NULL;
779
780 rcu_read_lock();
781 list_for_each_entry_rcu(pos, &tps61050_info_list, list) {
782 if (pos->pdata->num == dev1) {
783 sync1 = pos;
784 break;
785 }
786 }
787 pos = NULL;
788 list_for_each_entry_rcu(pos, &tps61050_info_list, list) {
789 if (pos->pdata->num == dev2) {
790 sync2 = pos;
791 break;
792 }
793 }
794 rcu_read_unlock();
795 if (sync1 != NULL)
796 sync1->s_info = NULL;
797 if (sync2 != NULL)
798 sync2->s_info = NULL;
799 if (!dev1 && !dev2)
800 return 0; /* no err if default instance 0's used */
801
802 if (dev1 == dev2)
803 return -EINVAL; /* err if sync instance is itself */
804
805 if ((sync1 != NULL) && (sync2 != NULL)) {
806 sync1->s_info = sync2;
807 sync2->s_info = sync1;
808 }
809 return 0;
810}
811
812static int tps61050_sync_dis(struct tps61050_info *info)
813{
814 if (info->s_info != NULL) {
815 info->s_info->s_mode = 0;
816 info->s_info->s_info = NULL;
817 info->s_mode = 0;
818 info->s_info = NULL;
819 return 0;
820 }
821
822 return -EINVAL;
823}
824
825static int tps61050_open(struct inode *inode, struct file *file)
826{
827 struct tps61050_info *info = NULL;
828 struct tps61050_info *pos = NULL;
829 int err;
830
831 rcu_read_lock();
832 list_for_each_entry_rcu(pos, &tps61050_info_list, list) {
833 if (pos->miscdev.minor == iminor(inode)) {
834 info = pos;
835 break;
836 }
837 }
838 rcu_read_unlock();
839 if (!info)
840 return -ENODEV;
841
842 err = tps61050_sync_en(info->pdata->num, info->pdata->sync);
843 if (err == -EINVAL)
844 dev_err(&info->i2c_client->dev,
845 "%s err: invalid num (%u) and sync (%u) instance\n",
846 __func__, info->pdata->num, info->pdata->sync);
847 if (atomic_xchg(&info->in_use, 1))
848 return -EBUSY;
849
850 if (info->s_info != NULL) {
851 if (atomic_xchg(&info->s_info->in_use, 1))
852 return -EBUSY;
853 }
854
855 file->private_data = info;
856 dev_dbg(&info->i2c_client->dev, "%s\n", __func__);
857 return 0;
858}
859
860static int tps61050_release(struct inode *inode, struct file *file)
861{
862 struct tps61050_info *info = file->private_data;
863
864 dev_dbg(&info->i2c_client->dev, "%s\n", __func__);
865 tps61050_pm_wr_s(info, NVC_PWR_OFF);
866 file->private_data = NULL;
867 WARN_ON(!atomic_xchg(&info->in_use, 0));
868 if (info->s_info != NULL)
869 WARN_ON(!atomic_xchg(&info->s_info->in_use, 0));
870 tps61050_sync_dis(info);
871 return 0;
872}
873
874static const struct file_operations tps61050_fileops = {
875 .owner = THIS_MODULE,
876 .open = tps61050_open,
877 .unlocked_ioctl = tps61050_ioctl,
878 .release = tps61050_release,
879};
880
881static void tps61050_del(struct tps61050_info *info)
882{
883 tps61050_pm_exit(info);
884 tps61050_sync_dis(info);
885 spin_lock(&tps61050_spinlock);
886 list_del_rcu(&info->list);
887 spin_unlock(&tps61050_spinlock);
888 synchronize_rcu();
889}
890
891static int tps61050_remove(struct i2c_client *client)
892{
893 struct tps61050_info *info = i2c_get_clientdata(client);
894
895 dev_dbg(&info->i2c_client->dev, "%s\n", __func__);
896 misc_deregister(&info->miscdev);
897 tps61050_del(info);
898 return 0;
899}
900
901static int tps61050_probe(
902 struct i2c_client *client,
903 const struct i2c_device_id *id)
904{
905 struct tps61050_info *info;
906 char dname[16];
907 int err;
908
909 dev_dbg(&client->dev, "%s\n", __func__);
910 info = devm_kzalloc(&client->dev, sizeof(*info), GFP_KERNEL);
911 if (info == NULL) {
912 dev_err(&client->dev, "%s: kzalloc error\n", __func__);
913 return -ENOMEM;
914 }
915
916 info->i2c_client = client;
917 if (client->dev.platform_data) {
918 info->pdata = client->dev.platform_data;
919 } else {
920 info->pdata = &tps61050_default_pdata;
921 dev_dbg(&client->dev,
922 "%s No platform data. Using defaults.\n",
923 __func__);
924 }
925 i2c_set_clientdata(client, info);
926 INIT_LIST_HEAD(&info->list);
927 spin_lock(&tps61050_spinlock);
928 list_add_rcu(&info->list, &tps61050_info_list);
929 spin_unlock(&tps61050_spinlock);
930 tps61050_pm_init(info);
931 err = tps61050_dev_id(info);
932 if (err < 0) {
933 dev_err(&client->dev, "%s device not found\n", __func__);
934 if (info->pdata->cfg & NVC_CFG_NODEV) {
935 tps61050_del(info);
936 return -ENODEV;
937 }
938 } else {
939 dev_dbg(&client->dev, "%s device found\n", __func__);
940 }
941
942 if (info->pdata->dev_name != 0)
943 strcpy(dname, info->pdata->dev_name);
944 else
945 strcpy(dname, "tps61050");
946 if (info->pdata->num)
947 snprintf(dname, sizeof(dname), "%s.%u",
948 dname, info->pdata->num);
949 info->miscdev.name = dname;
950 info->miscdev.fops = &tps61050_fileops;
951 info->miscdev.minor = MISC_DYNAMIC_MINOR;
952 if (misc_register(&info->miscdev)) {
953 dev_err(&client->dev, "%s unable to register misc device %s\n",
954 __func__, dname);
955 tps61050_del(info);
956 return -ENODEV;
957 }
958
959 return 0;
960}
961
962static const struct i2c_device_id tps61050_id[] = {
963 { "tps61050", 0 },
964 { },
965};
966
967MODULE_DEVICE_TABLE(i2c, tps61050_id);
968
969static struct i2c_driver tps61050_i2c_driver = {
970 .driver = {
971 .name = "tps61050",
972 .owner = THIS_MODULE,
973 },
974 .id_table = tps61050_id,
975 .probe = tps61050_probe,
976 .remove = tps61050_remove,
977};
978
979static int __init tps61050_init(void)
980{
981 return i2c_add_driver(&tps61050_i2c_driver);
982}
983
984static void __exit tps61050_exit(void)
985{
986 i2c_del_driver(&tps61050_i2c_driver);
987}
988
989module_init(tps61050_init);
990module_exit(tps61050_exit);
991MODULE_LICENSE("GPL");