2 * Copyright (C) 2008-2009 QUALCOMM Incorporated.
4 #include <linux/slab.h>
5 #include <linux/uaccess.h>
6 #include <linux/interrupt.h>
8 #include "msm_vfe8x_proc.h"
13 struct mutex vfe_lock;
14 static void *vfe_syncdata;
16 static int vfe_enable(struct camera_enable_cmd *enable)
22 static int vfe_disable(struct camera_enable_cmd *enable,
23 struct platform_device *dev)
29 msm_camio_disable(dev);
33 static void vfe_release(struct platform_device *dev)
35 msm_camio_disable(dev);
38 mutex_lock(&vfe_lock);
40 mutex_unlock(&vfe_lock);
43 static void vfe_config_axi(int mode,
44 struct axidata *ad, struct vfe_cmd_axi_output_config *ao)
46 struct msm_pmem_region *regptr;
50 if (mode == OUTPUT_1 || mode == OUTPUT_1_AND_2) {
53 i < ad->bufnum1; i++) {
55 p1 = &(ao->output1.outputY.outFragments[i][0]);
56 p2 = &(ao->output1.outputCbcr.outFragments[i][0]);
59 j < ao->output1.fragmentCount; j++) {
61 *p1 = regptr->paddr + regptr->y_off;
64 *p2 = regptr->paddr + regptr->cbcr_off;
69 } /* if OUTPUT1 or Both */
71 if (mode == OUTPUT_2 || mode == OUTPUT_1_AND_2) {
73 regptr = &(ad->region[ad->bufnum1]);
74 CDBG("bufnum2 = %d\n", ad->bufnum2);
77 i < ad->bufnum2; i++) {
79 p1 = &(ao->output2.outputY.outFragments[i][0]);
80 p2 = &(ao->output2.outputCbcr.outFragments[i][0]);
82 CDBG("config_axi: O2, phy = 0x%lx, y_off = %d, cbcr_off = %d\n",
83 regptr->paddr, regptr->y_off, regptr->cbcr_off);
86 j < ao->output2.fragmentCount; j++) {
88 *p1 = regptr->paddr + regptr->y_off;
89 CDBG("vfe_config_axi: p1 = 0x%x\n", *p1);
92 *p2 = regptr->paddr + regptr->cbcr_off;
93 CDBG("vfe_config_axi: p2 = 0x%x\n", *p2);
101 static int vfe_proc_general(struct msm_vfe_command_8k *cmd)
105 CDBG("vfe_proc_general: cmdID = %d\n", cmd->id);
108 case VFE_CMD_ID_RESET:
109 msm_camio_vfe_blk_reset();
110 msm_camio_camif_pad_reg_reset_2();
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))
120 /* msm_camio_camif_pad_reg_reset_2(); */
121 msm_camio_camif_pad_reg_reset();
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))
132 vfe_camif_config(&camif);
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))
142 vfe_black_level_config(&bl);
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))
152 vfe_roll_off_config(&rolloff);
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))
162 /* demux is always enabled. */
163 vfe_demux_channel_gain_config(&demuxc);
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))
173 vfe_demosaic_config(&demosaic);
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))
184 vfe_fov_crop_config(&fov);
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))
195 vfe_main_scaler_config(&mainds);
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))
206 vfe_white_balance_config(&wb);
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))
217 vfe_color_correction_config(&cc);
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))
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))
237 rc = vfe_rgb_gamma_config(&rgb);
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))
248 vfe_chroma_enhan_config(&chrom);
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))
259 vfe_chroma_sup_config(&chromsup);
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))
269 vfe_asf_config(&asf);
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))
280 vfe_scaler2y_config(&ds2y);
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))
291 vfe_scaler2cbcr_config(&ds2cbcr);
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))
301 vfe_chroma_subsample_config(&sub);
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))
311 vfe_frame_skip_config(&fskip);
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))
321 vfe_output_clamp_config(&clamp);
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))
332 vfe_black_level_update(&blk);
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))
342 vfe_demux_channel_gain_update(&dmu);
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))
352 vfe_demosaic_bpc_update(&demo_bpc);
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))
362 vfe_demosaic_abf_update(&demo_abf);
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))
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))
382 rc = vfe_rgb_gamma_update(&rgb);
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))
392 vfe_asf_update(&asf);
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))
402 vfe_frame_skip_update(&fskip);
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))
412 vfe_camif_frame_update(&fup);
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))
423 vfe_stats_update_af(&afup);
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))
433 vfe_stats_update_wb_exp(&wbexp);
437 /* control of start, stop, update, etc... */
438 case VFE_CMD_ID_STOP:
442 case VFE_CMD_ID_GET_HW_VERSION:
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))
452 vfe_stats_setting(&stats);
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))
462 vfe_stats_start_af(&af);
466 case VFE_CMD_ID_STATS_AUTOFOCUS_STOP:
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))
476 vfe_stats_start_wb_exp(&awexp);
480 case VFE_CMD_ID_STATS_WB_EXP_STOP:
481 vfe_stats_wb_exp_stop();
484 case VFE_CMD_ID_ASYNC_TIMER_SETTING:
487 case VFE_CMD_ID_UPDATE:
492 case VFE_CMD_ID_TEST_GEN_START:
496 acknowledge from upper layer
497 these are not in general command.
499 case VFE_CMD_ID_OUTPUT1_ACK:
501 case VFE_CMD_ID_OUTPUT2_ACK:
503 case VFE_CMD_ID_EPOCH1_ACK:
505 case VFE_CMD_ID_EPOCH2_ACK:
507 case VFE_CMD_ID_STATS_AUTOFOCUS_ACK:
509 case VFE_CMD_ID_STATS_WB_EXP_ACK:
520 static int vfe_config(struct msm_vfe_cfg_cmd *cmd, void *data)
522 struct msm_pmem_region *regptr;
523 struct msm_vfe_command_8k vfecmd;
527 void *cmd_data = NULL;
530 struct vfe_cmd_axi_output_config *axio = NULL;
531 struct vfe_cmd_stats_setting *scfg = NULL;
533 if (cmd->cmd_type != CMD_FRAME_BUF_RELEASE &&
534 cmd->cmd_type != CMD_STATS_BUF_RELEASE) {
536 if (copy_from_user(&vfecmd,
537 (void __user *)(cmd->value),
538 sizeof(struct msm_vfe_command_8k)))
542 CDBG("vfe_config: cmdType = %d\n", cmd->cmd_type);
544 switch (cmd->cmd_type) {
546 rc = vfe_proc_general(&vfecmd);
549 case CMD_STATS_ENABLE:
550 case CMD_STATS_AXI_CFG: {
551 struct axidata *axid;
558 kmalloc(sizeof(struct vfe_cmd_stats_setting),
563 if (copy_from_user(scfg,
564 (void __user *)(vfecmd.value),
571 regptr = axid->region;
572 if (axid->bufnum1 > 0) {
573 for (i = 0; i < axid->bufnum1; i++) {
575 (uint32_t)(regptr->paddr);
580 if (axid->bufnum2 > 0) {
581 for (i = 0; i < axid->bufnum2; i++) {
583 (uint32_t)(regptr->paddr);
588 vfe_stats_config(scfg);
592 case CMD_STATS_AF_AXI_CFG: {
596 case CMD_FRAME_BUF_RELEASE: {
597 /* preview buffer release */
600 struct vfe_cmd_output_ack fack;
605 b = (struct msm_frame *)(cmd->value);
606 p = *(unsigned long *)data;
608 b->path = MSM_FRAME_ENC;
611 (uint32_t)(p + b->y_off);
613 fack.chromabufaddr[0] =
614 (uint32_t)(p + b->cbcr_off);
616 if (b->path == MSM_FRAME_PREV_1)
617 vfe_output1_ack(&fack);
619 if (b->path == MSM_FRAME_ENC ||
620 b->path == MSM_FRAME_PREV_2)
621 vfe_output2_ack(&fack);
625 case CMD_SNAP_BUF_RELEASE: {
629 case CMD_STATS_BUF_RELEASE: {
630 struct vfe_cmd_stats_wb_exp_ack sack;
635 sack.nextWbExpOutputBufferAddr = *(uint32_t *)data;
636 vfe_stats_wb_exp_ack(&sack);
640 case CMD_AXI_CFG_OUT1: {
641 struct axidata *axid;
647 axio = memdup_user((void __user *)(vfecmd.value),
648 sizeof(struct vfe_cmd_axi_output_config));
650 return PTR_ERR(axio);
652 vfe_config_axi(OUTPUT_1, axid, axio);
653 vfe_axi_output_config(axio);
657 case CMD_AXI_CFG_OUT2:
658 case CMD_RAW_PICT_AXI_CFG: {
659 struct axidata *axid;
665 axio = memdup_user((void __user *)(vfecmd.value),
666 sizeof(struct vfe_cmd_axi_output_config));
668 return PTR_ERR(axio);
670 vfe_config_axi(OUTPUT_2, axid, axio);
672 axio->outputDataSize = 0;
673 vfe_axi_output_config(axio);
677 case CMD_AXI_CFG_SNAP_O1_AND_O2: {
678 struct axidata *axid;
683 axio = memdup_user((void __user *)(vfecmd.value),
684 sizeof(struct vfe_cmd_axi_output_config));
686 return PTR_ERR(axio);
688 vfe_config_axi(OUTPUT_1_AND_2,
690 vfe_axi_output_config(axio);
704 if (cmd->length > 256 &&
706 (cmd->cmd_type == CMD_GENERAL ||
707 cmd->cmd_type == CMD_STATS_DISABLE)) {
714 static int vfe_init(struct msm_vfe_callback *presp,
715 struct platform_device *dev)
719 rc = vfe_cmd_init(presp, dev, vfe_syncdata);
723 /* Bring up all the required GPIOs and Clocks */
724 return msm_camio_enable(dev);
727 void msm_camvfe_fn_init(struct msm_camvfe_fn *fptr, void *data)
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;