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 13struct mutex vfe_lock; 14static void *vfe_syncdata; 15 16static int vfe_enable(struct camera_enable_cmd *enable) 17{ 18 int rc = 0; 19 return rc; 20} 21 22static 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 33static 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 43static 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 101static 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 520static 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 714static 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 727void 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} 737