]> bbs.cooldavid.org Git - net-next-2.6.git/blob - drivers/staging/dream/camera/msm_vfe8x.c
d87d56f914de832cd3e398abd84f707cd7795729
[net-next-2.6.git] / drivers / staging / dream / camera / msm_vfe8x.c
1 /*
2  * Copyright (C) 2008-2009 QUALCOMM Incorporated.
3  */
4 #include <linux/slab.h>
5 #include <linux/uaccess.h>
6 #include <linux/interrupt.h>
7 #include <mach/irqs.h>
8 #include "msm_vfe8x_proc.h"
9
10 #define ON  1
11 #define OFF 0
12
13 struct mutex vfe_lock;
14 static void     *vfe_syncdata;
15
16 static int vfe_enable(struct camera_enable_cmd *enable)
17 {
18         int rc = 0;
19         return rc;
20 }
21
22 static int vfe_disable(struct camera_enable_cmd *enable,
23         struct platform_device *dev)
24 {
25         int rc = 0;
26
27         vfe_stop();
28
29         msm_camio_disable(dev);
30         return rc;
31 }
32
33 static void vfe_release(struct platform_device *dev)
34 {
35         msm_camio_disable(dev);
36         vfe_cmd_release(dev);
37
38         mutex_lock(&vfe_lock);
39         vfe_syncdata = NULL;
40         mutex_unlock(&vfe_lock);
41 }
42
43 static void vfe_config_axi(int mode,
44         struct axidata *ad, struct vfe_cmd_axi_output_config *ao)
45 {
46         struct msm_pmem_region *regptr;
47         int i, j;
48         uint32_t *p1, *p2;
49
50         if (mode == OUTPUT_1 || mode == OUTPUT_1_AND_2) {
51                 regptr = ad->region;
52                 for (i = 0;
53                         i < ad->bufnum1; i++) {
54
55                         p1 = &(ao->output1.outputY.outFragments[i][0]);
56                         p2 = &(ao->output1.outputCbcr.outFragments[i][0]);
57
58                         for (j = 0;
59                                 j < ao->output1.fragmentCount; j++) {
60
61                                 *p1 = regptr->paddr + regptr->y_off;
62                                 p1++;
63
64                                 *p2 = regptr->paddr + regptr->cbcr_off;
65                                 p2++;
66                         }
67                         regptr++;
68                 }
69         } /* if OUTPUT1 or Both */
70
71         if (mode == OUTPUT_2 || mode == OUTPUT_1_AND_2) {
72
73                 regptr = &(ad->region[ad->bufnum1]);
74                 CDBG("bufnum2 = %d\n", ad->bufnum2);
75
76                 for (i = 0;
77                         i < ad->bufnum2; i++) {
78
79                         p1 = &(ao->output2.outputY.outFragments[i][0]);
80                         p2 = &(ao->output2.outputCbcr.outFragments[i][0]);
81
82                 CDBG("config_axi: O2, phy = 0x%lx, y_off = %d, cbcr_off = %d\n",
83                         regptr->paddr, regptr->y_off, regptr->cbcr_off);
84
85                         for (j = 0;
86                                 j < ao->output2.fragmentCount; j++) {
87
88                                 *p1 = regptr->paddr + regptr->y_off;
89                                 CDBG("vfe_config_axi: p1 = 0x%x\n", *p1);
90                                 p1++;
91
92                                 *p2 = regptr->paddr + regptr->cbcr_off;
93                                 CDBG("vfe_config_axi: p2 = 0x%x\n", *p2);
94                                 p2++;
95                         }
96                         regptr++;
97                 }
98         }
99 }
100
101 static int vfe_proc_general(struct msm_vfe_command_8k *cmd)
102 {
103         int rc = 0;
104
105         CDBG("vfe_proc_general: cmdID = %d\n", cmd->id);
106
107         switch (cmd->id) {
108         case VFE_CMD_ID_RESET:
109                 msm_camio_vfe_blk_reset();
110                 msm_camio_camif_pad_reg_reset_2();
111                 vfe_reset();
112                 break;
113
114         case VFE_CMD_ID_START: {
115                 struct vfe_cmd_start start;
116                 if (copy_from_user(&start,
117                         (void __user *) cmd->value, cmd->length))
118                         rc = -EFAULT;
119
120                 /* msm_camio_camif_pad_reg_reset_2(); */
121                 msm_camio_camif_pad_reg_reset();
122                 vfe_start(&start);
123         }
124                 break;
125
126         case VFE_CMD_ID_CAMIF_CONFIG: {
127                 struct vfe_cmd_camif_config camif;
128                 if (copy_from_user(&camif,
129                         (void __user *) cmd->value, cmd->length))
130                         rc = -EFAULT;
131
132                 vfe_camif_config(&camif);
133         }
134                 break;
135
136         case VFE_CMD_ID_BLACK_LEVEL_CONFIG: {
137                 struct vfe_cmd_black_level_config bl;
138                 if (copy_from_user(&bl,
139                         (void __user *) cmd->value, cmd->length))
140                         rc = -EFAULT;
141
142                 vfe_black_level_config(&bl);
143         }
144                 break;
145
146         case VFE_CMD_ID_ROLL_OFF_CONFIG: {
147                 struct vfe_cmd_roll_off_config rolloff;
148                 if (copy_from_user(&rolloff,
149                         (void __user *) cmd->value, cmd->length))
150                         rc = -EFAULT;
151
152                 vfe_roll_off_config(&rolloff);
153         }
154                 break;
155
156         case VFE_CMD_ID_DEMUX_CHANNEL_GAIN_CONFIG: {
157                 struct vfe_cmd_demux_channel_gain_config demuxc;
158                 if (copy_from_user(&demuxc,
159                         (void __user *) cmd->value, cmd->length))
160                         rc = -EFAULT;
161
162                 /* demux is always enabled.  */
163                 vfe_demux_channel_gain_config(&demuxc);
164         }
165                 break;
166
167         case VFE_CMD_ID_DEMOSAIC_CONFIG: {
168                 struct vfe_cmd_demosaic_config demosaic;
169                 if (copy_from_user(&demosaic,
170                         (void __user *) cmd->value, cmd->length))
171                         rc = -EFAULT;
172
173                 vfe_demosaic_config(&demosaic);
174         }
175                 break;
176
177         case VFE_CMD_ID_FOV_CROP_CONFIG:
178         case VFE_CMD_ID_FOV_CROP_UPDATE: {
179                 struct vfe_cmd_fov_crop_config fov;
180                 if (copy_from_user(&fov,
181                         (void __user *) cmd->value, cmd->length))
182                         rc = -EFAULT;
183
184                 vfe_fov_crop_config(&fov);
185         }
186                 break;
187
188         case VFE_CMD_ID_MAIN_SCALER_CONFIG:
189         case VFE_CMD_ID_MAIN_SCALER_UPDATE: {
190                 struct vfe_cmd_main_scaler_config mainds;
191                 if (copy_from_user(&mainds,
192                         (void __user *) cmd->value, cmd->length))
193                         rc = -EFAULT;
194
195                 vfe_main_scaler_config(&mainds);
196         }
197                 break;
198
199         case VFE_CMD_ID_WHITE_BALANCE_CONFIG:
200         case VFE_CMD_ID_WHITE_BALANCE_UPDATE: {
201                 struct vfe_cmd_white_balance_config wb;
202                 if (copy_from_user(&wb,
203                         (void __user *) cmd->value, cmd->length))
204                         rc = -EFAULT;
205
206                 vfe_white_balance_config(&wb);
207         }
208                 break;
209
210         case VFE_CMD_ID_COLOR_CORRECTION_CONFIG:
211         case VFE_CMD_ID_COLOR_CORRECTION_UPDATE: {
212                 struct vfe_cmd_color_correction_config cc;
213                 if (copy_from_user(&cc,
214                         (void __user *) cmd->value, cmd->length))
215                         rc = -EFAULT;
216
217                 vfe_color_correction_config(&cc);
218         }
219                 break;
220
221         case VFE_CMD_ID_LA_CONFIG: {
222                 struct vfe_cmd_la_config la;
223                 if (copy_from_user(&la,
224                         (void __user *) cmd->value, cmd->length))
225                         rc = -EFAULT;
226
227                 vfe_la_config(&la);
228         }
229                 break;
230
231         case VFE_CMD_ID_RGB_GAMMA_CONFIG: {
232                 struct vfe_cmd_rgb_gamma_config rgb;
233                 if (copy_from_user(&rgb,
234                         (void __user *) cmd->value, cmd->length))
235                         rc = -EFAULT;
236
237                 rc = vfe_rgb_gamma_config(&rgb);
238         }
239                 break;
240
241         case VFE_CMD_ID_CHROMA_ENHAN_CONFIG:
242         case VFE_CMD_ID_CHROMA_ENHAN_UPDATE: {
243                 struct vfe_cmd_chroma_enhan_config chrom;
244                 if (copy_from_user(&chrom,
245                         (void __user *) cmd->value, cmd->length))
246                         rc = -EFAULT;
247
248                 vfe_chroma_enhan_config(&chrom);
249         }
250                 break;
251
252         case VFE_CMD_ID_CHROMA_SUPPRESSION_CONFIG:
253         case VFE_CMD_ID_CHROMA_SUPPRESSION_UPDATE: {
254                 struct vfe_cmd_chroma_suppression_config chromsup;
255                 if (copy_from_user(&chromsup,
256                         (void __user *) cmd->value, cmd->length))
257                         rc = -EFAULT;
258
259                 vfe_chroma_sup_config(&chromsup);
260         }
261                 break;
262
263         case VFE_CMD_ID_ASF_CONFIG: {
264                 struct vfe_cmd_asf_config asf;
265                 if (copy_from_user(&asf,
266                         (void __user *) cmd->value, cmd->length))
267                         rc = -EFAULT;
268
269                 vfe_asf_config(&asf);
270         }
271                 break;
272
273         case VFE_CMD_ID_SCALER2Y_CONFIG:
274         case VFE_CMD_ID_SCALER2Y_UPDATE: {
275                 struct vfe_cmd_scaler2_config ds2y;
276                 if (copy_from_user(&ds2y,
277                         (void __user *) cmd->value, cmd->length))
278                         rc = -EFAULT;
279
280                 vfe_scaler2y_config(&ds2y);
281         }
282                 break;
283
284         case VFE_CMD_ID_SCALER2CbCr_CONFIG:
285         case VFE_CMD_ID_SCALER2CbCr_UPDATE: {
286                 struct vfe_cmd_scaler2_config ds2cbcr;
287                 if (copy_from_user(&ds2cbcr,
288                         (void __user *) cmd->value, cmd->length))
289                         rc = -EFAULT;
290
291                 vfe_scaler2cbcr_config(&ds2cbcr);
292         }
293                 break;
294
295         case VFE_CMD_ID_CHROMA_SUBSAMPLE_CONFIG: {
296                 struct vfe_cmd_chroma_subsample_config sub;
297                 if (copy_from_user(&sub,
298                         (void __user *) cmd->value, cmd->length))
299                         rc = -EFAULT;
300
301                 vfe_chroma_subsample_config(&sub);
302         }
303                 break;
304
305         case VFE_CMD_ID_FRAME_SKIP_CONFIG: {
306                 struct vfe_cmd_frame_skip_config fskip;
307                 if (copy_from_user(&fskip,
308                         (void __user *) cmd->value, cmd->length))
309                         rc = -EFAULT;
310
311                 vfe_frame_skip_config(&fskip);
312         }
313                 break;
314
315         case VFE_CMD_ID_OUTPUT_CLAMP_CONFIG: {
316                 struct vfe_cmd_output_clamp_config clamp;
317                 if (copy_from_user(&clamp,
318                         (void __user *) cmd->value, cmd->length))
319                         rc = -EFAULT;
320
321                 vfe_output_clamp_config(&clamp);
322         }
323                 break;
324
325         /* module update commands */
326         case VFE_CMD_ID_BLACK_LEVEL_UPDATE: {
327                 struct vfe_cmd_black_level_config blk;
328                 if (copy_from_user(&blk,
329                         (void __user *) cmd->value, cmd->length))
330                         rc = -EFAULT;
331
332                 vfe_black_level_update(&blk);
333         }
334                 break;
335
336         case VFE_CMD_ID_DEMUX_CHANNEL_GAIN_UPDATE: {
337                 struct vfe_cmd_demux_channel_gain_config dmu;
338                 if (copy_from_user(&dmu,
339                         (void __user *) cmd->value, cmd->length))
340                         rc = -EFAULT;
341
342                 vfe_demux_channel_gain_update(&dmu);
343         }
344                 break;
345
346         case VFE_CMD_ID_DEMOSAIC_BPC_UPDATE: {
347                 struct vfe_cmd_demosaic_bpc_update demo_bpc;
348                 if (copy_from_user(&demo_bpc,
349                         (void __user *) cmd->value, cmd->length))
350                         rc = -EFAULT;
351
352                 vfe_demosaic_bpc_update(&demo_bpc);
353         }
354                 break;
355
356         case VFE_CMD_ID_DEMOSAIC_ABF_UPDATE: {
357                 struct vfe_cmd_demosaic_abf_update demo_abf;
358                 if (copy_from_user(&demo_abf,
359                         (void __user *) cmd->value, cmd->length))
360                         rc = -EFAULT;
361
362                 vfe_demosaic_abf_update(&demo_abf);
363         }
364                 break;
365
366         case VFE_CMD_ID_LA_UPDATE: {
367                 struct vfe_cmd_la_config la;
368                 if (copy_from_user(&la,
369                         (void __user *) cmd->value, cmd->length))
370                         rc = -EFAULT;
371
372                 vfe_la_update(&la);
373         }
374                 break;
375
376         case VFE_CMD_ID_RGB_GAMMA_UPDATE: {
377                 struct vfe_cmd_rgb_gamma_config rgb;
378                 if (copy_from_user(&rgb,
379                         (void __user *) cmd->value, cmd->length))
380                         rc = -EFAULT;
381
382                 rc = vfe_rgb_gamma_update(&rgb);
383         }
384                 break;
385
386         case VFE_CMD_ID_ASF_UPDATE: {
387                 struct vfe_cmd_asf_update asf;
388                 if (copy_from_user(&asf,
389                         (void __user *) cmd->value, cmd->length))
390                         rc = -EFAULT;
391
392                 vfe_asf_update(&asf);
393         }
394                 break;
395
396         case VFE_CMD_ID_FRAME_SKIP_UPDATE: {
397                 struct vfe_cmd_frame_skip_update fskip;
398                 if (copy_from_user(&fskip,
399                         (void __user *) cmd->value, cmd->length))
400                         rc = -EFAULT;
401
402                 vfe_frame_skip_update(&fskip);
403         }
404                 break;
405
406         case VFE_CMD_ID_CAMIF_FRAME_UPDATE: {
407                 struct vfe_cmds_camif_frame fup;
408                 if (copy_from_user(&fup,
409                         (void __user *) cmd->value, cmd->length))
410                         rc = -EFAULT;
411
412                 vfe_camif_frame_update(&fup);
413         }
414                 break;
415
416         /* stats update commands */
417         case VFE_CMD_ID_STATS_AUTOFOCUS_UPDATE: {
418                 struct vfe_cmd_stats_af_update afup;
419                 if (copy_from_user(&afup,
420                         (void __user *) cmd->value, cmd->length))
421                         rc = -EFAULT;
422
423                 vfe_stats_update_af(&afup);
424         }
425                 break;
426
427         case VFE_CMD_ID_STATS_WB_EXP_UPDATE: {
428                 struct vfe_cmd_stats_wb_exp_update wbexp;
429                 if (copy_from_user(&wbexp,
430                         (void __user *) cmd->value, cmd->length))
431                         rc = -EFAULT;
432
433                 vfe_stats_update_wb_exp(&wbexp);
434         }
435                 break;
436
437         /* control of start, stop, update, etc... */
438         case VFE_CMD_ID_STOP:
439                 vfe_stop();
440                 break;
441
442         case VFE_CMD_ID_GET_HW_VERSION:
443                 break;
444
445         /* stats */
446         case VFE_CMD_ID_STATS_SETTING: {
447                 struct vfe_cmd_stats_setting stats;
448                 if (copy_from_user(&stats,
449                         (void __user *) cmd->value, cmd->length))
450                         rc = -EFAULT;
451
452                 vfe_stats_setting(&stats);
453         }
454                 break;
455
456         case VFE_CMD_ID_STATS_AUTOFOCUS_START: {
457                 struct vfe_cmd_stats_af_start af;
458                 if (copy_from_user(&af,
459                         (void __user *) cmd->value, cmd->length))
460                         rc = -EFAULT;
461
462                 vfe_stats_start_af(&af);
463         }
464                 break;
465
466         case VFE_CMD_ID_STATS_AUTOFOCUS_STOP:
467                 vfe_stats_af_stop();
468                 break;
469
470         case VFE_CMD_ID_STATS_WB_EXP_START: {
471                 struct vfe_cmd_stats_wb_exp_start awexp;
472                 if (copy_from_user(&awexp,
473                         (void __user *) cmd->value, cmd->length))
474                         rc = -EFAULT;
475
476                 vfe_stats_start_wb_exp(&awexp);
477         }
478                 break;
479
480         case VFE_CMD_ID_STATS_WB_EXP_STOP:
481                 vfe_stats_wb_exp_stop();
482                 break;
483
484         case VFE_CMD_ID_ASYNC_TIMER_SETTING:
485                 break;
486
487         case VFE_CMD_ID_UPDATE:
488                 vfe_update();
489                 break;
490
491         /* test gen */
492         case VFE_CMD_ID_TEST_GEN_START:
493                 break;
494
495 /*
496   acknowledge from upper layer
497         these are not in general command.
498
499         case VFE_CMD_ID_OUTPUT1_ACK:
500                 break;
501         case VFE_CMD_ID_OUTPUT2_ACK:
502                 break;
503         case VFE_CMD_ID_EPOCH1_ACK:
504                 break;
505         case VFE_CMD_ID_EPOCH2_ACK:
506                 break;
507         case VFE_CMD_ID_STATS_AUTOFOCUS_ACK:
508                 break;
509         case VFE_CMD_ID_STATS_WB_EXP_ACK:
510                 break;
511 */
512
513         default:
514                 break;
515         } /* switch */
516
517         return rc;
518 }
519
520 static int vfe_config(struct msm_vfe_cfg_cmd *cmd, void *data)
521 {
522         struct msm_pmem_region *regptr;
523         struct msm_vfe_command_8k vfecmd;
524
525         uint32_t i;
526
527         void *cmd_data = NULL;
528         long rc = 0;
529
530         struct vfe_cmd_axi_output_config *axio = NULL;
531         struct vfe_cmd_stats_setting *scfg = NULL;
532
533         if (cmd->cmd_type != CMD_FRAME_BUF_RELEASE &&
534             cmd->cmd_type != CMD_STATS_BUF_RELEASE) {
535
536                 if (copy_from_user(&vfecmd,
537                                 (void __user *)(cmd->value),
538                                 sizeof(struct msm_vfe_command_8k)))
539                         return -EFAULT;
540         }
541
542         CDBG("vfe_config: cmdType = %d\n", cmd->cmd_type);
543
544         switch (cmd->cmd_type) {
545         case CMD_GENERAL:
546                 rc = vfe_proc_general(&vfecmd);
547                 break;
548
549         case CMD_STATS_ENABLE:
550         case CMD_STATS_AXI_CFG: {
551                 struct axidata *axid;
552
553                 axid = data;
554                 if (!axid)
555                         return -EFAULT;
556
557                 scfg =
558                         kmalloc(sizeof(struct vfe_cmd_stats_setting),
559                                 GFP_ATOMIC);
560                 if (!scfg)
561                         return -ENOMEM;
562
563                 if (copy_from_user(scfg,
564                                         (void __user *)(vfecmd.value),
565                                         vfecmd.length)) {
566
567                         kfree(scfg);
568                         return -EFAULT;
569                 }
570
571                 regptr = axid->region;
572                 if (axid->bufnum1 > 0) {
573                         for (i = 0; i < axid->bufnum1; i++) {
574                                 scfg->awbBuffer[i] =
575                                         (uint32_t)(regptr->paddr);
576                                 regptr++;
577                         }
578                 }
579
580                 if (axid->bufnum2 > 0) {
581                         for (i = 0; i < axid->bufnum2; i++) {
582                                 scfg->afBuffer[i] =
583                                         (uint32_t)(regptr->paddr);
584                                 regptr++;
585                         }
586                 }
587
588                 vfe_stats_config(scfg);
589         }
590                 break;
591
592         case CMD_STATS_AF_AXI_CFG: {
593         }
594                 break;
595
596         case CMD_FRAME_BUF_RELEASE: {
597                 /* preview buffer release */
598                 struct msm_frame *b;
599                 unsigned long p;
600                 struct vfe_cmd_output_ack fack;
601
602                 if (!data)
603                         return -EFAULT;
604
605                 b = (struct msm_frame *)(cmd->value);
606                 p = *(unsigned long *)data;
607
608                 b->path = MSM_FRAME_ENC;
609
610                 fack.ybufaddr[0] =
611                         (uint32_t)(p + b->y_off);
612
613                 fack.chromabufaddr[0] =
614                         (uint32_t)(p + b->cbcr_off);
615
616                 if (b->path == MSM_FRAME_PREV_1)
617                         vfe_output1_ack(&fack);
618
619                 if (b->path == MSM_FRAME_ENC ||
620                     b->path == MSM_FRAME_PREV_2)
621                         vfe_output2_ack(&fack);
622         }
623                 break;
624
625         case CMD_SNAP_BUF_RELEASE: {
626         }
627                 break;
628
629         case CMD_STATS_BUF_RELEASE: {
630                 struct vfe_cmd_stats_wb_exp_ack sack;
631
632                 if (!data)
633                         return -EFAULT;
634
635                 sack.nextWbExpOutputBufferAddr = *(uint32_t *)data;
636                 vfe_stats_wb_exp_ack(&sack);
637         }
638                 break;
639
640         case CMD_AXI_CFG_OUT1: {
641                 struct axidata *axid;
642
643                 axid = data;
644                 if (!axid)
645                         return -EFAULT;
646
647                 axio = memdup_user((void __user *)(vfecmd.value),
648                                    sizeof(struct vfe_cmd_axi_output_config));
649                 if (IS_ERR(axio))
650                         return PTR_ERR(axio);
651
652                 vfe_config_axi(OUTPUT_1, axid, axio);
653                 vfe_axi_output_config(axio);
654         }
655                 break;
656
657         case CMD_AXI_CFG_OUT2:
658         case CMD_RAW_PICT_AXI_CFG: {
659                 struct axidata *axid;
660
661                 axid = data;
662                 if (!axid)
663                         return -EFAULT;
664
665                 axio = memdup_user((void __user *)(vfecmd.value),
666                                    sizeof(struct vfe_cmd_axi_output_config));
667                 if (IS_ERR(axio))
668                         return PTR_ERR(axio);
669
670                 vfe_config_axi(OUTPUT_2, axid, axio);
671
672                 axio->outputDataSize = 0;
673                 vfe_axi_output_config(axio);
674         }
675                 break;
676
677         case CMD_AXI_CFG_SNAP_O1_AND_O2: {
678                 struct axidata *axid;
679                 axid = data;
680                 if (!axid)
681                         return -EFAULT;
682
683                 axio = memdup_user((void __user *)(vfecmd.value),
684                                    sizeof(struct vfe_cmd_axi_output_config));
685                 if (IS_ERR(axio))
686                         return PTR_ERR(axio);
687
688                 vfe_config_axi(OUTPUT_1_AND_2,
689                         axid, axio);
690                 vfe_axi_output_config(axio);
691                 cmd_data = axio;
692         }
693                 break;
694
695         default:
696                 break;
697         } /* switch */
698
699         kfree(scfg);
700
701         kfree(axio);
702
703 /*
704         if (cmd->length > 256 &&
705                         cmd_data &&
706                         (cmd->cmd_type == CMD_GENERAL ||
707                          cmd->cmd_type == CMD_STATS_DISABLE)) {
708                 kfree(cmd_data);
709         }
710 */
711         return rc;
712 }
713
714 static int vfe_init(struct msm_vfe_callback *presp,
715         struct platform_device *dev)
716 {
717         int rc = 0;
718
719         rc = vfe_cmd_init(presp, dev, vfe_syncdata);
720         if (rc < 0)
721                 return rc;
722
723         /* Bring up all the required GPIOs and Clocks */
724         return msm_camio_enable(dev);
725 }
726
727 void msm_camvfe_fn_init(struct msm_camvfe_fn *fptr, void *data)
728 {
729         mutex_init(&vfe_lock);
730         fptr->vfe_init    = vfe_init;
731         fptr->vfe_enable  = vfe_enable;
732         fptr->vfe_config  = vfe_config;
733         fptr->vfe_disable = vfe_disable;
734         fptr->vfe_release = vfe_release;
735         vfe_syncdata = data;
736 }