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
;