2 * Copyright (C) 2008-2009 QUALCOMM Incorporated.
4 #include <linux/uaccess.h>
5 #include <linux/interrupt.h>
7 #include "msm_vfe8x_proc.h"
12 struct mutex vfe_lock;
13 static void *vfe_syncdata;
15 static int vfe_enable(struct camera_enable_cmd *enable)
21 static int vfe_disable(struct camera_enable_cmd *enable,
22 struct platform_device *dev)
28 msm_camio_disable(dev);
32 static void vfe_release(struct platform_device *dev)
34 msm_camio_disable(dev);
37 mutex_lock(&vfe_lock);
39 mutex_unlock(&vfe_lock);
42 static void vfe_config_axi(int mode,
43 struct axidata *ad, struct vfe_cmd_axi_output_config *ao)
45 struct msm_pmem_region *regptr;
49 if (mode == OUTPUT_1 || mode == OUTPUT_1_AND_2) {
52 i < ad->bufnum1; i++) {
54 p1 = &(ao->output1.outputY.outFragments[i][0]);
55 p2 = &(ao->output1.outputCbcr.outFragments[i][0]);
58 j < ao->output1.fragmentCount; j++) {
60 *p1 = regptr->paddr + regptr->y_off;
63 *p2 = regptr->paddr + regptr->cbcr_off;
68 } /* if OUTPUT1 or Both */
70 if (mode == OUTPUT_2 || mode == OUTPUT_1_AND_2) {
72 regptr = &(ad->region[ad->bufnum1]);
73 CDBG("bufnum2 = %d\n", ad->bufnum2);
76 i < ad->bufnum2; i++) {
78 p1 = &(ao->output2.outputY.outFragments[i][0]);
79 p2 = &(ao->output2.outputCbcr.outFragments[i][0]);
81 CDBG("config_axi: O2, phy = 0x%lx, y_off = %d, cbcr_off = %d\n",
82 regptr->paddr, regptr->y_off, regptr->cbcr_off);
85 j < ao->output2.fragmentCount; j++) {
87 *p1 = regptr->paddr + regptr->y_off;
88 CDBG("vfe_config_axi: p1 = 0x%x\n", *p1);
91 *p2 = regptr->paddr + regptr->cbcr_off;
92 CDBG("vfe_config_axi: p2 = 0x%x\n", *p2);
100 static int vfe_proc_general(struct msm_vfe_command_8k *cmd)
104 CDBG("vfe_proc_general: cmdID = %d\n", cmd->id);
107 case VFE_CMD_ID_RESET:
108 msm_camio_vfe_blk_reset();
109 msm_camio_camif_pad_reg_reset_2();
113 case VFE_CMD_ID_START: {
114 struct vfe_cmd_start start;
115 if (copy_from_user(&start,
116 (void __user *) cmd->value, cmd->length))
119 /* msm_camio_camif_pad_reg_reset_2(); */
120 msm_camio_camif_pad_reg_reset();
125 case VFE_CMD_ID_CAMIF_CONFIG: {
126 struct vfe_cmd_camif_config camif;
127 if (copy_from_user(&camif,
128 (void __user *) cmd->value, cmd->length))
131 vfe_camif_config(&camif);
135 case VFE_CMD_ID_BLACK_LEVEL_CONFIG: {
136 struct vfe_cmd_black_level_config bl;
137 if (copy_from_user(&bl,
138 (void __user *) cmd->value, cmd->length))
141 vfe_black_level_config(&bl);
145 case VFE_CMD_ID_ROLL_OFF_CONFIG: {
146 struct vfe_cmd_roll_off_config rolloff;
147 if (copy_from_user(&rolloff,
148 (void __user *) cmd->value, cmd->length))
151 vfe_roll_off_config(&rolloff);
155 case VFE_CMD_ID_DEMUX_CHANNEL_GAIN_CONFIG: {
156 struct vfe_cmd_demux_channel_gain_config demuxc;
157 if (copy_from_user(&demuxc,
158 (void __user *) cmd->value, cmd->length))
161 /* demux is always enabled. */
162 vfe_demux_channel_gain_config(&demuxc);
166 case VFE_CMD_ID_DEMOSAIC_CONFIG: {
167 struct vfe_cmd_demosaic_config demosaic;
168 if (copy_from_user(&demosaic,
169 (void __user *) cmd->value, cmd->length))
172 vfe_demosaic_config(&demosaic);
176 case VFE_CMD_ID_FOV_CROP_CONFIG:
177 case VFE_CMD_ID_FOV_CROP_UPDATE: {
178 struct vfe_cmd_fov_crop_config fov;
179 if (copy_from_user(&fov,
180 (void __user *) cmd->value, cmd->length))
183 vfe_fov_crop_config(&fov);
187 case VFE_CMD_ID_MAIN_SCALER_CONFIG:
188 case VFE_CMD_ID_MAIN_SCALER_UPDATE: {
189 struct vfe_cmd_main_scaler_config mainds;
190 if (copy_from_user(&mainds,
191 (void __user *) cmd->value, cmd->length))
194 vfe_main_scaler_config(&mainds);
198 case VFE_CMD_ID_WHITE_BALANCE_CONFIG:
199 case VFE_CMD_ID_WHITE_BALANCE_UPDATE: {
200 struct vfe_cmd_white_balance_config wb;
201 if (copy_from_user(&wb,
202 (void __user *) cmd->value, cmd->length))
205 vfe_white_balance_config(&wb);
209 case VFE_CMD_ID_COLOR_CORRECTION_CONFIG:
210 case VFE_CMD_ID_COLOR_CORRECTION_UPDATE: {
211 struct vfe_cmd_color_correction_config cc;
212 if (copy_from_user(&cc,
213 (void __user *) cmd->value, cmd->length))
216 vfe_color_correction_config(&cc);
220 case VFE_CMD_ID_LA_CONFIG: {
221 struct vfe_cmd_la_config la;
222 if (copy_from_user(&la,
223 (void __user *) cmd->value, cmd->length))
230 case VFE_CMD_ID_RGB_GAMMA_CONFIG: {
231 struct vfe_cmd_rgb_gamma_config rgb;
232 if (copy_from_user(&rgb,
233 (void __user *) cmd->value, cmd->length))
236 rc = vfe_rgb_gamma_config(&rgb);
240 case VFE_CMD_ID_CHROMA_ENHAN_CONFIG:
241 case VFE_CMD_ID_CHROMA_ENHAN_UPDATE: {
242 struct vfe_cmd_chroma_enhan_config chrom;
243 if (copy_from_user(&chrom,
244 (void __user *) cmd->value, cmd->length))
247 vfe_chroma_enhan_config(&chrom);
251 case VFE_CMD_ID_CHROMA_SUPPRESSION_CONFIG:
252 case VFE_CMD_ID_CHROMA_SUPPRESSION_UPDATE: {
253 struct vfe_cmd_chroma_suppression_config chromsup;
254 if (copy_from_user(&chromsup,
255 (void __user *) cmd->value, cmd->length))
258 vfe_chroma_sup_config(&chromsup);
262 case VFE_CMD_ID_ASF_CONFIG: {
263 struct vfe_cmd_asf_config asf;
264 if (copy_from_user(&asf,
265 (void __user *) cmd->value, cmd->length))
268 vfe_asf_config(&asf);
272 case VFE_CMD_ID_SCALER2Y_CONFIG:
273 case VFE_CMD_ID_SCALER2Y_UPDATE: {
274 struct vfe_cmd_scaler2_config ds2y;
275 if (copy_from_user(&ds2y,
276 (void __user *) cmd->value, cmd->length))
279 vfe_scaler2y_config(&ds2y);
283 case VFE_CMD_ID_SCALER2CbCr_CONFIG:
284 case VFE_CMD_ID_SCALER2CbCr_UPDATE: {
285 struct vfe_cmd_scaler2_config ds2cbcr;
286 if (copy_from_user(&ds2cbcr,
287 (void __user *) cmd->value, cmd->length))
290 vfe_scaler2cbcr_config(&ds2cbcr);
294 case VFE_CMD_ID_CHROMA_SUBSAMPLE_CONFIG: {
295 struct vfe_cmd_chroma_subsample_config sub;
296 if (copy_from_user(&sub,
297 (void __user *) cmd->value, cmd->length))
300 vfe_chroma_subsample_config(&sub);
304 case VFE_CMD_ID_FRAME_SKIP_CONFIG: {
305 struct vfe_cmd_frame_skip_config fskip;
306 if (copy_from_user(&fskip,
307 (void __user *) cmd->value, cmd->length))
310 vfe_frame_skip_config(&fskip);
314 case VFE_CMD_ID_OUTPUT_CLAMP_CONFIG: {
315 struct vfe_cmd_output_clamp_config clamp;
316 if (copy_from_user(&clamp,
317 (void __user *) cmd->value, cmd->length))
320 vfe_output_clamp_config(&clamp);
324 /* module update commands */
325 case VFE_CMD_ID_BLACK_LEVEL_UPDATE: {
326 struct vfe_cmd_black_level_config blk;
327 if (copy_from_user(&blk,
328 (void __user *) cmd->value, cmd->length))
331 vfe_black_level_update(&blk);
335 case VFE_CMD_ID_DEMUX_CHANNEL_GAIN_UPDATE: {
336 struct vfe_cmd_demux_channel_gain_config dmu;
337 if (copy_from_user(&dmu,
338 (void __user *) cmd->value, cmd->length))
341 vfe_demux_channel_gain_update(&dmu);
345 case VFE_CMD_ID_DEMOSAIC_BPC_UPDATE: {
346 struct vfe_cmd_demosaic_bpc_update demo_bpc;
347 if (copy_from_user(&demo_bpc,
348 (void __user *) cmd->value, cmd->length))
351 vfe_demosaic_bpc_update(&demo_bpc);
355 case VFE_CMD_ID_DEMOSAIC_ABF_UPDATE: {
356 struct vfe_cmd_demosaic_abf_update demo_abf;
357 if (copy_from_user(&demo_abf,
358 (void __user *) cmd->value, cmd->length))
361 vfe_demosaic_abf_update(&demo_abf);
365 case VFE_CMD_ID_LA_UPDATE: {
366 struct vfe_cmd_la_config la;
367 if (copy_from_user(&la,
368 (void __user *) cmd->value, cmd->length))
375 case VFE_CMD_ID_RGB_GAMMA_UPDATE: {
376 struct vfe_cmd_rgb_gamma_config rgb;
377 if (copy_from_user(&rgb,
378 (void __user *) cmd->value, cmd->length))
381 rc = vfe_rgb_gamma_update(&rgb);
385 case VFE_CMD_ID_ASF_UPDATE: {
386 struct vfe_cmd_asf_update asf;
387 if (copy_from_user(&asf,
388 (void __user *) cmd->value, cmd->length))
391 vfe_asf_update(&asf);
395 case VFE_CMD_ID_FRAME_SKIP_UPDATE: {
396 struct vfe_cmd_frame_skip_update fskip;
397 if (copy_from_user(&fskip,
398 (void __user *) cmd->value, cmd->length))
401 vfe_frame_skip_update(&fskip);
405 case VFE_CMD_ID_CAMIF_FRAME_UPDATE: {
406 struct vfe_cmds_camif_frame fup;
407 if (copy_from_user(&fup,
408 (void __user *) cmd->value, cmd->length))
411 vfe_camif_frame_update(&fup);
415 /* stats update commands */
416 case VFE_CMD_ID_STATS_AUTOFOCUS_UPDATE: {
417 struct vfe_cmd_stats_af_update afup;
418 if (copy_from_user(&afup,
419 (void __user *) cmd->value, cmd->length))
422 vfe_stats_update_af(&afup);
426 case VFE_CMD_ID_STATS_WB_EXP_UPDATE: {
427 struct vfe_cmd_stats_wb_exp_update wbexp;
428 if (copy_from_user(&wbexp,
429 (void __user *) cmd->value, cmd->length))
432 vfe_stats_update_wb_exp(&wbexp);
436 /* control of start, stop, update, etc... */
437 case VFE_CMD_ID_STOP:
441 case VFE_CMD_ID_GET_HW_VERSION:
445 case VFE_CMD_ID_STATS_SETTING: {
446 struct vfe_cmd_stats_setting stats;
447 if (copy_from_user(&stats,
448 (void __user *) cmd->value, cmd->length))
451 vfe_stats_setting(&stats);
455 case VFE_CMD_ID_STATS_AUTOFOCUS_START: {
456 struct vfe_cmd_stats_af_start af;
457 if (copy_from_user(&af,
458 (void __user *) cmd->value, cmd->length))
461 vfe_stats_start_af(&af);
465 case VFE_CMD_ID_STATS_AUTOFOCUS_STOP:
469 case VFE_CMD_ID_STATS_WB_EXP_START: {
470 struct vfe_cmd_stats_wb_exp_start awexp;
471 if (copy_from_user(&awexp,
472 (void __user *) cmd->value, cmd->length))
475 vfe_stats_start_wb_exp(&awexp);
479 case VFE_CMD_ID_STATS_WB_EXP_STOP:
480 vfe_stats_wb_exp_stop();
483 case VFE_CMD_ID_ASYNC_TIMER_SETTING:
486 case VFE_CMD_ID_UPDATE:
491 case VFE_CMD_ID_TEST_GEN_START:
495 acknowledge from upper layer
496 these are not in general command.
498 case VFE_CMD_ID_OUTPUT1_ACK:
500 case VFE_CMD_ID_OUTPUT2_ACK:
502 case VFE_CMD_ID_EPOCH1_ACK:
504 case VFE_CMD_ID_EPOCH2_ACK:
506 case VFE_CMD_ID_STATS_AUTOFOCUS_ACK:
508 case VFE_CMD_ID_STATS_WB_EXP_ACK:
519 static int vfe_config(struct msm_vfe_cfg_cmd *cmd, void *data)
521 struct msm_pmem_region *regptr;
522 struct msm_vfe_command_8k vfecmd;
526 void *cmd_data = NULL;
529 struct vfe_cmd_axi_output_config *axio = NULL;
530 struct vfe_cmd_stats_setting *scfg = NULL;
532 if (cmd->cmd_type != CMD_FRAME_BUF_RELEASE &&
533 cmd->cmd_type != CMD_STATS_BUF_RELEASE) {
535 if (copy_from_user(&vfecmd,
536 (void __user *)(cmd->value),
537 sizeof(struct msm_vfe_command_8k)))
541 CDBG("vfe_config: cmdType = %d\n", cmd->cmd_type);
543 switch (cmd->cmd_type) {
545 rc = vfe_proc_general(&vfecmd);
548 case CMD_STATS_ENABLE:
549 case CMD_STATS_AXI_CFG: {
550 struct axidata *axid;
557 kmalloc(sizeof(struct vfe_cmd_stats_setting),
562 if (copy_from_user(scfg,
563 (void __user *)(vfecmd.value),
570 regptr = axid->region;
571 if (axid->bufnum1 > 0) {
572 for (i = 0; i < axid->bufnum1; i++) {
574 (uint32_t)(regptr->paddr);
579 if (axid->bufnum2 > 0) {
580 for (i = 0; i < axid->bufnum2; i++) {
582 (uint32_t)(regptr->paddr);
587 vfe_stats_config(scfg);
591 case CMD_STATS_AF_AXI_CFG: {
595 case CMD_FRAME_BUF_RELEASE: {
596 /* preview buffer release */
599 struct vfe_cmd_output_ack fack;
604 b = (struct msm_frame *)(cmd->value);
605 p = *(unsigned long *)data;
607 b->path = MSM_FRAME_ENC;
610 (uint32_t)(p + b->y_off);
612 fack.chromabufaddr[0] =
613 (uint32_t)(p + b->cbcr_off);
615 if (b->path == MSM_FRAME_PREV_1)
616 vfe_output1_ack(&fack);
618 if (b->path == MSM_FRAME_ENC ||
619 b->path == MSM_FRAME_PREV_2)
620 vfe_output2_ack(&fack);
624 case CMD_SNAP_BUF_RELEASE: {
628 case CMD_STATS_BUF_RELEASE: {
629 struct vfe_cmd_stats_wb_exp_ack sack;
634 sack.nextWbExpOutputBufferAddr = *(uint32_t *)data;
635 vfe_stats_wb_exp_ack(&sack);
639 case CMD_AXI_CFG_OUT1: {
640 struct axidata *axid;
647 kmalloc(sizeof(struct vfe_cmd_axi_output_config),
652 if (copy_from_user(axio, (void __user *)(vfecmd.value),
653 sizeof(struct vfe_cmd_axi_output_config))) {
658 vfe_config_axi(OUTPUT_1, axid, axio);
659 vfe_axi_output_config(axio);
663 case CMD_AXI_CFG_OUT2:
664 case CMD_RAW_PICT_AXI_CFG: {
665 struct axidata *axid;
672 kmalloc(sizeof(struct vfe_cmd_axi_output_config),
677 if (copy_from_user(axio, (void __user *)(vfecmd.value),
678 sizeof(struct vfe_cmd_axi_output_config))) {
683 vfe_config_axi(OUTPUT_2, axid, axio);
685 axio->outputDataSize = 0;
686 vfe_axi_output_config(axio);
690 case CMD_AXI_CFG_SNAP_O1_AND_O2: {
691 struct axidata *axid;
697 kmalloc(sizeof(struct vfe_cmd_axi_output_config),
702 if (copy_from_user(axio, (void __user *)(vfecmd.value),
703 sizeof(struct vfe_cmd_axi_output_config))) {
708 vfe_config_axi(OUTPUT_1_AND_2,
710 vfe_axi_output_config(axio);
724 if (cmd->length > 256 &&
726 (cmd->cmd_type == CMD_GENERAL ||
727 cmd->cmd_type == CMD_STATS_DISABLE)) {
734 static int vfe_init(struct msm_vfe_callback *presp,
735 struct platform_device *dev)
739 rc = vfe_cmd_init(presp, dev, vfe_syncdata);
743 /* Bring up all the required GPIOs and Clocks */
744 return msm_camio_enable(dev);
747 void msm_camvfe_fn_init(struct msm_camvfe_fn *fptr, void *data)
749 mutex_init(&vfe_lock);
750 fptr->vfe_init = vfe_init;
751 fptr->vfe_enable = vfe_enable;
752 fptr->vfe_config = vfe_config;
753 fptr->vfe_disable = vfe_disable;
754 fptr->vfe_release = vfe_release;