1/* 2 * Copyright (C) 2008-2009 QUALCOMM Incorporated. 3 */ 4 5 6#include <linux/kernel.h> 7#include <linux/module.h> 8#include <linux/slab.h> 9#include <linux/init.h> 10#include <linux/sched.h> 11#include <mach/board.h> 12 13#include <linux/fs.h> 14#include <linux/list.h> 15#include <linux/uaccess.h> 16#include <linux/android_pmem.h> 17#include <linux/poll.h> 18#include <media/msm_camera.h> 19#include <mach/camera.h> 20 21#define MSM_MAX_CAMERA_SENSORS 5 22 23#define ERR_USER_COPY(to) pr_err("%s(%d): copy %s user\n", \ 24 __func__, __LINE__, ((to) ? "to" : "from")) 25#define ERR_COPY_FROM_USER() ERR_USER_COPY(0) 26#define ERR_COPY_TO_USER() ERR_USER_COPY(1) 27 28static struct class *msm_class; 29static dev_t msm_devno; 30static LIST_HEAD(msm_sensors); 31 32#define __CONTAINS(r, v, l, field) ({ \ 33 typeof(r) __r = r; \ 34 typeof(v) __v = v; \ 35 typeof(v) __e = __v + l; \ 36 int res = __v >= __r->field && \ 37 __e <= __r->field + __r->len; \ 38 res; \ 39}) 40 41#define CONTAINS(r1, r2, field) ({ \ 42 typeof(r2) __r2 = r2; \ 43 __CONTAINS(r1, __r2->field, __r2->len, field); \ 44}) 45 46#define IN_RANGE(r, v, field) ({ \ 47 typeof(r) __r = r; \ 48 typeof(v) __vv = v; \ 49 int res = ((__vv >= __r->field) && \ 50 (__vv < (__r->field + __r->len))); \ 51 res; \ 52}) 53 54#define OVERLAPS(r1, r2, field) ({ \ 55 typeof(r1) __r1 = r1; \ 56 typeof(r2) __r2 = r2; \ 57 typeof(__r2->field) __v = __r2->field; \ 58 typeof(__v) __e = __v + __r2->len - 1; \ 59 int res = (IN_RANGE(__r1, __v, field) || \ 60 IN_RANGE(__r1, __e, field)); \ 61 res; \ 62}) 63 64#define MSM_DRAIN_QUEUE_NOSYNC(sync, name) do { \ 65 struct msm_queue_cmd *qcmd = NULL; \ 66 CDBG("%s: draining queue "#name"\n", __func__); \ 67 while (!list_empty(&(sync)->name)) { \ 68 qcmd = list_first_entry(&(sync)->name, \ 69 struct msm_queue_cmd, list); \ 70 list_del_init(&qcmd->list); \ 71 kfree(qcmd); \ 72 }; \ 73} while (0) 74 75#define MSM_DRAIN_QUEUE(sync, name) do { \ 76 unsigned long flags; \ 77 spin_lock_irqsave(&(sync)->name##_lock, flags); \ 78 MSM_DRAIN_QUEUE_NOSYNC(sync, name); \ 79 spin_unlock_irqrestore(&(sync)->name##_lock, flags); \ 80} while (0) 81 82static int check_overlap(struct hlist_head *ptype, 83 unsigned long paddr, 84 unsigned long len) 85{ 86 struct msm_pmem_region *region; 87 struct msm_pmem_region t = { .paddr = paddr, .len = len }; 88 struct hlist_node *node; 89 90 hlist_for_each_entry(region, node, ptype, list) { 91 if (CONTAINS(region, &t, paddr) || 92 CONTAINS(&t, region, paddr) || 93 OVERLAPS(region, &t, paddr)) { 94 printk(KERN_ERR 95 " region (PHYS %p len %ld)" 96 " clashes with registered region" 97 " (paddr %p len %ld)\n", 98 (void *)t.paddr, t.len, 99 (void *)region->paddr, region->len); 100 return -1; 101 } 102 } 103 104 return 0; 105} 106 107static int msm_pmem_table_add(struct hlist_head *ptype, 108 struct msm_pmem_info *info) 109{ 110 struct file *file; 111 unsigned long paddr; 112 unsigned long vstart; 113 unsigned long len; 114 int rc; 115 struct msm_pmem_region *region; 116 117 rc = get_pmem_file(info->fd, &paddr, &vstart, &len, &file); 118 if (rc < 0) { 119 pr_err("msm_pmem_table_add: get_pmem_file fd %d error %d\n", 120 info->fd, rc); 121 return rc; 122 } 123 124 if (check_overlap(ptype, paddr, len) < 0) 125 return -EINVAL; 126 127 CDBG("%s: type = %d, paddr = 0x%lx, vaddr = 0x%lx\n", 128 __func__, 129 info->type, paddr, (unsigned long)info->vaddr); 130 131 region = kmalloc(sizeof(*region), GFP_KERNEL); 132 if (!region) 133 return -ENOMEM; 134 135 INIT_HLIST_NODE(®ion->list); 136 137 region->type = info->type; 138 region->vaddr = info->vaddr; 139 region->paddr = paddr; 140 region->len = len; 141 region->file = file; 142 region->y_off = info->y_off; 143 region->cbcr_off = info->cbcr_off; 144 region->fd = info->fd; 145 region->active = info->active; 146 147 hlist_add_head(&(region->list), ptype); 148 149 return 0; 150} 151 152/* return of 0 means failure */ 153static uint8_t msm_pmem_region_lookup(struct hlist_head *ptype, 154 int pmem_type, struct msm_pmem_region *reg, uint8_t maxcount) 155{ 156 struct msm_pmem_region *region; 157 struct msm_pmem_region *regptr; 158 struct hlist_node *node, *n; 159 160 uint8_t rc = 0; 161 162 regptr = reg; 163 164 hlist_for_each_entry_safe(region, node, n, ptype, list) { 165 if (region->type == pmem_type && region->active) { 166 *regptr = *region; 167 rc += 1; 168 if (rc >= maxcount) 169 break; 170 regptr++; 171 } 172 } 173 174 return rc; 175} 176 177static unsigned long msm_pmem_frame_ptov_lookup(struct msm_sync *sync, 178 unsigned long pyaddr, 179 unsigned long pcbcraddr, 180 uint32_t *yoff, uint32_t *cbcroff, int *fd) 181{ 182 struct msm_pmem_region *region; 183 struct hlist_node *node, *n; 184 185 hlist_for_each_entry_safe(region, node, n, &sync->frame, list) { 186 if (pyaddr == (region->paddr + region->y_off) && 187 pcbcraddr == (region->paddr + 188 region->cbcr_off) && 189 region->active) { 190 /* offset since we could pass vaddr inside 191 * a registerd pmem buffer 192 */ 193 *yoff = region->y_off; 194 *cbcroff = region->cbcr_off; 195 *fd = region->fd; 196 region->active = 0; 197 return (unsigned long)(region->vaddr); 198 } 199 } 200 201 return 0; 202} 203 204static unsigned long msm_pmem_stats_ptov_lookup(struct msm_sync *sync, 205 unsigned long addr, int *fd) 206{ 207 struct msm_pmem_region *region; 208 struct hlist_node *node, *n; 209 210 hlist_for_each_entry_safe(region, node, n, &sync->stats, list) { 211 if (addr == region->paddr && region->active) { 212 /* offset since we could pass vaddr inside a 213 * registered pmem buffer */ 214 *fd = region->fd; 215 region->active = 0; 216 return (unsigned long)(region->vaddr); 217 } 218 } 219 220 return 0; 221} 222 223static unsigned long msm_pmem_frame_vtop_lookup(struct msm_sync *sync, 224 unsigned long buffer, 225 uint32_t yoff, uint32_t cbcroff, int fd) 226{ 227 struct msm_pmem_region *region; 228 struct hlist_node *node, *n; 229 230 hlist_for_each_entry_safe(region, 231 node, n, &sync->frame, list) { 232 if (((unsigned long)(region->vaddr) == buffer) && 233 (region->y_off == yoff) && 234 (region->cbcr_off == cbcroff) && 235 (region->fd == fd) && 236 (region->active == 0)) { 237 238 region->active = 1; 239 return region->paddr; 240 } 241 } 242 243 return 0; 244} 245 246static unsigned long msm_pmem_stats_vtop_lookup( 247 struct msm_sync *sync, 248 unsigned long buffer, 249 int fd) 250{ 251 struct msm_pmem_region *region; 252 struct hlist_node *node, *n; 253 254 hlist_for_each_entry_safe(region, node, n, &sync->stats, list) { 255 if (((unsigned long)(region->vaddr) == buffer) && 256 (region->fd == fd) && region->active == 0) { 257 region->active = 1; 258 return region->paddr; 259 } 260 } 261 262 return 0; 263} 264 265static int __msm_pmem_table_del(struct msm_sync *sync, 266 struct msm_pmem_info *pinfo) 267{ 268 int rc = 0; 269 struct msm_pmem_region *region; 270 struct hlist_node *node, *n; 271 272 switch (pinfo->type) { 273 case MSM_PMEM_OUTPUT1: 274 case MSM_PMEM_OUTPUT2: 275 case MSM_PMEM_THUMBAIL: 276 case MSM_PMEM_MAINIMG: 277 case MSM_PMEM_RAW_MAINIMG: 278 hlist_for_each_entry_safe(region, node, n, 279 &sync->frame, list) { 280 281 if (pinfo->type == region->type && 282 pinfo->vaddr == region->vaddr && 283 pinfo->fd == region->fd) { 284 hlist_del(node); 285 put_pmem_file(region->file); 286 kfree(region); 287 } 288 } 289 break; 290 291 case MSM_PMEM_AEC_AWB: 292 case MSM_PMEM_AF: 293 hlist_for_each_entry_safe(region, node, n, 294 &sync->stats, list) { 295 296 if (pinfo->type == region->type && 297 pinfo->vaddr == region->vaddr && 298 pinfo->fd == region->fd) { 299 hlist_del(node); 300 put_pmem_file(region->file); 301 kfree(region); 302 } 303 } 304 break; 305 306 default: 307 rc = -EINVAL; 308 break; 309 } 310 311 return rc; 312} 313 314static int msm_pmem_table_del(struct msm_sync *sync, void __user *arg) 315{ 316 struct msm_pmem_info info; 317 318 if (copy_from_user(&info, arg, sizeof(info))) { 319 ERR_COPY_FROM_USER(); 320 return -EFAULT; 321 } 322 323 return __msm_pmem_table_del(sync, &info); 324} 325 326static int __msm_get_frame(struct msm_sync *sync, 327 struct msm_frame *frame) 328{ 329 unsigned long flags; 330 int rc = 0; 331 332 struct msm_queue_cmd *qcmd = NULL; 333 struct msm_vfe_phy_info *pphy; 334 335 spin_lock_irqsave(&sync->prev_frame_q_lock, flags); 336 if (!list_empty(&sync->prev_frame_q)) { 337 qcmd = list_first_entry(&sync->prev_frame_q, 338 struct msm_queue_cmd, list); 339 list_del_init(&qcmd->list); 340 } 341 spin_unlock_irqrestore(&sync->prev_frame_q_lock, flags); 342 343 if (!qcmd) { 344 pr_err("%s: no preview frame.\n", __func__); 345 return -EAGAIN; 346 } 347 348 pphy = (struct msm_vfe_phy_info *)(qcmd->command); 349 350 frame->buffer = 351 msm_pmem_frame_ptov_lookup(sync, 352 pphy->y_phy, 353 pphy->cbcr_phy, &(frame->y_off), 354 &(frame->cbcr_off), &(frame->fd)); 355 if (!frame->buffer) { 356 pr_err("%s: cannot get frame, invalid lookup address " 357 "y=%x cbcr=%x offset=%d\n", 358 __func__, 359 pphy->y_phy, 360 pphy->cbcr_phy, 361 frame->y_off); 362 rc = -EINVAL; 363 } 364 365 CDBG("__msm_get_frame: y=0x%x, cbcr=0x%x, qcmd=0x%x, virt_addr=0x%x\n", 366 pphy->y_phy, pphy->cbcr_phy, (int) qcmd, (int) frame->buffer); 367 368 kfree(qcmd); 369 return rc; 370} 371 372static int msm_get_frame(struct msm_sync *sync, void __user *arg) 373{ 374 int rc = 0; 375 struct msm_frame frame; 376 377 if (copy_from_user(&frame, 378 arg, 379 sizeof(struct msm_frame))) { 380 ERR_COPY_FROM_USER(); 381 return -EFAULT; 382 } 383 384 rc = __msm_get_frame(sync, &frame); 385 if (rc < 0) 386 return rc; 387 388 if (sync->croplen) { 389 if (frame.croplen > sync->croplen) { 390 pr_err("msm_get_frame: invalid frame croplen %d\n", 391 frame.croplen); 392 return -EINVAL; 393 } 394 395 if (copy_to_user((void *)frame.cropinfo, 396 sync->cropinfo, 397 sync->croplen)) { 398 ERR_COPY_TO_USER(); 399 return -EFAULT; 400 } 401 } 402 403 if (copy_to_user((void *)arg, 404 &frame, sizeof(struct msm_frame))) { 405 ERR_COPY_TO_USER(); 406 rc = -EFAULT; 407 } 408 409 CDBG("Got frame!!!\n"); 410 411 return rc; 412} 413 414static int msm_enable_vfe(struct msm_sync *sync, void __user *arg) 415{ 416 int rc = -EIO; 417 struct camera_enable_cmd cfg; 418 419 if (copy_from_user(&cfg, 420 arg, 421 sizeof(struct camera_enable_cmd))) { 422 ERR_COPY_FROM_USER(); 423 return -EFAULT; 424 } 425 426 if (sync->vfefn.vfe_enable) 427 rc = sync->vfefn.vfe_enable(&cfg); 428 429 CDBG("msm_enable_vfe: returned rc = %d\n", rc); 430 return rc; 431} 432 433static int msm_disable_vfe(struct msm_sync *sync, void __user *arg) 434{ 435 int rc = -EIO; 436 struct camera_enable_cmd cfg; 437 438 if (copy_from_user(&cfg, 439 arg, 440 sizeof(struct camera_enable_cmd))) { 441 ERR_COPY_FROM_USER(); 442 return -EFAULT; 443 } 444 445 if (sync->vfefn.vfe_disable) 446 rc = sync->vfefn.vfe_disable(&cfg, NULL); 447 448 CDBG("msm_disable_vfe: returned rc = %d\n", rc); 449 return rc; 450} 451 452static struct msm_queue_cmd *__msm_control(struct msm_sync *sync, 453 struct msm_control_device_queue *queue, 454 struct msm_queue_cmd *qcmd, 455 int timeout) 456{ 457 unsigned long flags; 458 int rc; 459 460 spin_lock_irqsave(&sync->msg_event_q_lock, flags); 461 list_add_tail(&qcmd->list, &sync->msg_event_q); 462 /* wake up config thread */ 463 wake_up(&sync->msg_event_wait); 464 spin_unlock_irqrestore(&sync->msg_event_q_lock, flags); 465 466 if (!queue) 467 return NULL; 468 469 /* wait for config status */ 470 rc = wait_event_interruptible_timeout( 471 queue->ctrl_status_wait, 472 !list_empty_careful(&queue->ctrl_status_q), 473 timeout); 474 if (list_empty_careful(&queue->ctrl_status_q)) { 475 if (!rc) 476 rc = -ETIMEDOUT; 477 if (rc < 0) { 478 pr_err("msm_control: wait_event error %d\n", rc); 479 return ERR_PTR(rc); 480 } 481 } 482 483 /* control command status is ready */ 484 spin_lock_irqsave(&queue->ctrl_status_q_lock, flags); 485 BUG_ON(list_empty(&queue->ctrl_status_q)); 486 qcmd = list_first_entry(&queue->ctrl_status_q, 487 struct msm_queue_cmd, list); 488 list_del_init(&qcmd->list); 489 spin_unlock_irqrestore(&queue->ctrl_status_q_lock, flags); 490 491 return qcmd; 492} 493 494static int msm_control(struct msm_control_device *ctrl_pmsm, 495 int block, 496 void __user *arg) 497{ 498 int rc = 0; 499 500 struct msm_sync *sync = ctrl_pmsm->pmsm->sync; 501 struct msm_ctrl_cmd udata, *ctrlcmd; 502 struct msm_queue_cmd *qcmd = NULL, *qcmd_temp; 503 504 if (copy_from_user(&udata, arg, sizeof(struct msm_ctrl_cmd))) { 505 ERR_COPY_FROM_USER(); 506 rc = -EFAULT; 507 goto end; 508 } 509 510 qcmd = kmalloc(sizeof(struct msm_queue_cmd) + 511 sizeof(struct msm_ctrl_cmd) + udata.length, 512 GFP_KERNEL); 513 if (!qcmd) { 514 pr_err("msm_control: cannot allocate buffer\n"); 515 rc = -ENOMEM; 516 goto end; 517 } 518 519 qcmd->type = MSM_CAM_Q_CTRL; 520 qcmd->command = ctrlcmd = (struct msm_ctrl_cmd *)(qcmd + 1); 521 *ctrlcmd = udata; 522 ctrlcmd->value = ctrlcmd + 1; 523 524 if (udata.length) { 525 if (copy_from_user(ctrlcmd->value, 526 udata.value, udata.length)) { 527 ERR_COPY_FROM_USER(); 528 rc = -EFAULT; 529 goto end; 530 } 531 } 532 533 if (!block) { 534 /* qcmd will be set to NULL */ 535 qcmd = __msm_control(sync, NULL, qcmd, 0); 536 goto end; 537 } 538 539 qcmd_temp = __msm_control(sync, 540 &ctrl_pmsm->ctrl_q, 541 qcmd, MAX_SCHEDULE_TIMEOUT); 542 543 if (IS_ERR(qcmd_temp)) { 544 rc = PTR_ERR(qcmd_temp); 545 goto end; 546 } 547 qcmd = qcmd_temp; 548 549 if (qcmd->command) { 550 void __user *to = udata.value; 551 udata = *(struct msm_ctrl_cmd *)qcmd->command; 552 if (udata.length > 0) { 553 if (copy_to_user(to, 554 udata.value, 555 udata.length)) { 556 ERR_COPY_TO_USER(); 557 rc = -EFAULT; 558 goto end; 559 } 560 } 561 udata.value = to; 562 563 if (copy_to_user((void *)arg, &udata, 564 sizeof(struct msm_ctrl_cmd))) { 565 ERR_COPY_TO_USER(); 566 rc = -EFAULT; 567 goto end; 568 } 569 } 570 571end: 572 /* Note: if we get here as a result of an error, we will free the 573 * qcmd that we kmalloc() in this function. When we come here as 574 * a result of a successful completion, we are freeing the qcmd that 575 * we dequeued from queue->ctrl_status_q. 576 */ 577 kfree(qcmd); 578 579 CDBG("msm_control: end rc = %d\n", rc); 580 return rc; 581} 582 583static int msm_get_stats(struct msm_sync *sync, void __user *arg) 584{ 585 unsigned long flags; 586 int timeout; 587 int rc = 0; 588 589 struct msm_stats_event_ctrl se; 590 591 struct msm_queue_cmd *qcmd = NULL; 592 struct msm_ctrl_cmd *ctrl = NULL; 593 struct msm_vfe_resp *data = NULL; 594 struct msm_stats_buf stats; 595 596 if (copy_from_user(&se, arg, 597 sizeof(struct msm_stats_event_ctrl))) { 598 ERR_COPY_FROM_USER(); 599 return -EFAULT; 600 } 601 602 timeout = (int)se.timeout_ms; 603 604 CDBG("msm_get_stats timeout %d\n", timeout); 605 rc = wait_event_interruptible_timeout( 606 sync->msg_event_wait, 607 !list_empty_careful(&sync->msg_event_q), 608 msecs_to_jiffies(timeout)); 609 if (list_empty_careful(&sync->msg_event_q)) { 610 if (rc == 0) 611 rc = -ETIMEDOUT; 612 if (rc < 0) { 613 pr_err("msm_get_stats error %d\n", rc); 614 return rc; 615 } 616 } 617 CDBG("msm_get_stats returned from wait: %d\n", rc); 618 619 spin_lock_irqsave(&sync->msg_event_q_lock, flags); 620 BUG_ON(list_empty(&sync->msg_event_q)); 621 qcmd = list_first_entry(&sync->msg_event_q, 622 struct msm_queue_cmd, list); 623 list_del_init(&qcmd->list); 624 spin_unlock_irqrestore(&sync->msg_event_q_lock, flags); 625 626 CDBG("=== received from DSP === %d\n", qcmd->type); 627 628 switch (qcmd->type) { 629 case MSM_CAM_Q_VFE_EVT: 630 case MSM_CAM_Q_VFE_MSG: 631 data = (struct msm_vfe_resp *)(qcmd->command); 632 633 /* adsp event and message */ 634 se.resptype = MSM_CAM_RESP_STAT_EVT_MSG; 635 636 /* 0 - msg from aDSP, 1 - event from mARM */ 637 se.stats_event.type = data->evt_msg.type; 638 se.stats_event.msg_id = data->evt_msg.msg_id; 639 se.stats_event.len = data->evt_msg.len; 640 641 CDBG("msm_get_stats, qcmd->type = %d\n", qcmd->type); 642 CDBG("length = %d\n", se.stats_event.len); 643 CDBG("msg_id = %d\n", se.stats_event.msg_id); 644 645 if ((data->type == VFE_MSG_STATS_AF) || 646 (data->type == VFE_MSG_STATS_WE)) { 647 648 stats.buffer = 649 msm_pmem_stats_ptov_lookup(sync, 650 data->phy.sbuf_phy, 651 &(stats.fd)); 652 if (!stats.buffer) { 653 pr_err("%s: msm_pmem_stats_ptov_lookup error\n", 654 __func__); 655 rc = -EINVAL; 656 goto failure; 657 } 658 659 if (copy_to_user((void *)(se.stats_event.data), 660 &stats, 661 sizeof(struct msm_stats_buf))) { 662 ERR_COPY_TO_USER(); 663 rc = -EFAULT; 664 goto failure; 665 } 666 } else if ((data->evt_msg.len > 0) && 667 (data->type == VFE_MSG_GENERAL)) { 668 if (copy_to_user((void *)(se.stats_event.data), 669 data->evt_msg.data, 670 data->evt_msg.len)) { 671 ERR_COPY_TO_USER(); 672 rc = -EFAULT; 673 } 674 } else if (data->type == VFE_MSG_OUTPUT1 || 675 data->type == VFE_MSG_OUTPUT2) { 676 if (copy_to_user((void *)(se.stats_event.data), 677 data->extdata, 678 data->extlen)) { 679 ERR_COPY_TO_USER(); 680 rc = -EFAULT; 681 } 682 } else if (data->type == VFE_MSG_SNAPSHOT && sync->pict_pp) { 683 struct msm_postproc buf; 684 struct msm_pmem_region region; 685 buf.fmnum = msm_pmem_region_lookup(&sync->frame, 686 MSM_PMEM_MAINIMG, 687 ®ion, 1); 688 if (buf.fmnum == 1) { 689 buf.fmain.buffer = (unsigned long)region.vaddr; 690 buf.fmain.y_off = region.y_off; 691 buf.fmain.cbcr_off = region.cbcr_off; 692 buf.fmain.fd = region.fd; 693 } else { 694 buf.fmnum = msm_pmem_region_lookup(&sync->frame, 695 MSM_PMEM_RAW_MAINIMG, 696 ®ion, 1); 697 if (buf.fmnum == 1) { 698 buf.fmain.path = MSM_FRAME_PREV_2; 699 buf.fmain.buffer = 700 (unsigned long)region.vaddr; 701 buf.fmain.fd = region.fd; 702 } else { 703 pr_err("%s: pmem lookup failed\n", 704 __func__); 705 rc = -EINVAL; 706 } 707 } 708 709 if (copy_to_user((void *)(se.stats_event.data), &buf, 710 sizeof(buf))) { 711 ERR_COPY_TO_USER(); 712 rc = -EFAULT; 713 goto failure; 714 } 715 CDBG("snapshot copy_to_user!\n"); 716 } 717 break; 718 719 case MSM_CAM_Q_CTRL: 720 /* control command from control thread */ 721 ctrl = (struct msm_ctrl_cmd *)(qcmd->command); 722 723 CDBG("msm_get_stats, qcmd->type = %d\n", qcmd->type); 724 CDBG("length = %d\n", ctrl->length); 725 726 if (ctrl->length > 0) { 727 if (copy_to_user((void *)(se.ctrl_cmd.value), 728 ctrl->value, 729 ctrl->length)) { 730 ERR_COPY_TO_USER(); 731 rc = -EFAULT; 732 goto failure; 733 } 734 } 735 736 se.resptype = MSM_CAM_RESP_CTRL; 737 738 /* what to control */ 739 se.ctrl_cmd.type = ctrl->type; 740 se.ctrl_cmd.length = ctrl->length; 741 se.ctrl_cmd.resp_fd = ctrl->resp_fd; 742 break; 743 744 case MSM_CAM_Q_V4L2_REQ: 745 /* control command from v4l2 client */ 746 ctrl = (struct msm_ctrl_cmd *)(qcmd->command); 747 748 CDBG("msm_get_stats, qcmd->type = %d\n", qcmd->type); 749 CDBG("length = %d\n", ctrl->length); 750 751 if (ctrl->length > 0) { 752 if (copy_to_user((void *)(se.ctrl_cmd.value), 753 ctrl->value, ctrl->length)) { 754 ERR_COPY_TO_USER(); 755 rc = -EFAULT; 756 goto failure; 757 } 758 } 759 760 /* 2 tells config thread this is v4l2 request */ 761 se.resptype = MSM_CAM_RESP_V4L2; 762 763 /* what to control */ 764 se.ctrl_cmd.type = ctrl->type; 765 se.ctrl_cmd.length = ctrl->length; 766 break; 767 768 default: 769 rc = -EFAULT; 770 goto failure; 771 } /* switch qcmd->type */ 772 773 if (copy_to_user((void *)arg, &se, sizeof(se))) { 774 ERR_COPY_TO_USER(); 775 rc = -EFAULT; 776 } 777 778failure: 779 kfree(qcmd); 780 781 CDBG("msm_get_stats: %d\n", rc); 782 return rc; 783} 784 785static int msm_ctrl_cmd_done(struct msm_control_device *ctrl_pmsm, 786 void __user *arg) 787{ 788 unsigned long flags; 789 int rc = 0; 790 791 struct msm_ctrl_cmd udata, *ctrlcmd; 792 struct msm_queue_cmd *qcmd = NULL; 793 794 if (copy_from_user(&udata, arg, sizeof(struct msm_ctrl_cmd))) { 795 ERR_COPY_FROM_USER(); 796 rc = -EFAULT; 797 goto end; 798 } 799 800 qcmd = kmalloc(sizeof(struct msm_queue_cmd) + 801 sizeof(struct msm_ctrl_cmd) + udata.length, 802 GFP_KERNEL); 803 if (!qcmd) { 804 rc = -ENOMEM; 805 goto end; 806 } 807 808 qcmd->command = ctrlcmd = (struct msm_ctrl_cmd *)(qcmd + 1); 809 *ctrlcmd = udata; 810 if (udata.length > 0) { 811 ctrlcmd->value = ctrlcmd + 1; 812 if (copy_from_user(ctrlcmd->value, 813 (void *)udata.value, 814 udata.length)) { 815 ERR_COPY_FROM_USER(); 816 rc = -EFAULT; 817 kfree(qcmd); 818 goto end; 819 } 820 } else 821 ctrlcmd->value = NULL; 822 823end: 824 CDBG("msm_ctrl_cmd_done: end rc = %d\n", rc); 825 if (rc == 0) { 826 /* wake up control thread */ 827 spin_lock_irqsave(&ctrl_pmsm->ctrl_q.ctrl_status_q_lock, flags); 828 list_add_tail(&qcmd->list, &ctrl_pmsm->ctrl_q.ctrl_status_q); 829 wake_up(&ctrl_pmsm->ctrl_q.ctrl_status_wait); 830 spin_unlock_irqrestore(&ctrl_pmsm->ctrl_q.ctrl_status_q_lock, flags); 831 } 832 833 return rc; 834} 835 836static int msm_config_vfe(struct msm_sync *sync, void __user *arg) 837{ 838 struct msm_vfe_cfg_cmd cfgcmd; 839 struct msm_pmem_region region[8]; 840 struct axidata axi_data; 841 void *data = NULL; 842 int rc = -EIO; 843 844 memset(&axi_data, 0, sizeof(axi_data)); 845 846 if (copy_from_user(&cfgcmd, arg, sizeof(cfgcmd))) { 847 ERR_COPY_FROM_USER(); 848 return -EFAULT; 849 } 850 851 switch (cfgcmd.cmd_type) { 852 case CMD_STATS_ENABLE: 853 axi_data.bufnum1 = 854 msm_pmem_region_lookup(&sync->stats, 855 MSM_PMEM_AEC_AWB, ®ion[0], 856 NUM_WB_EXP_STAT_OUTPUT_BUFFERS); 857 if (!axi_data.bufnum1) { 858 pr_err("%s: pmem region lookup error\n", __func__); 859 return -EINVAL; 860 } 861 axi_data.region = ®ion[0]; 862 data = &axi_data; 863 break; 864 case CMD_STATS_AF_ENABLE: 865 axi_data.bufnum1 = 866 msm_pmem_region_lookup(&sync->stats, 867 MSM_PMEM_AF, ®ion[0], 868 NUM_AF_STAT_OUTPUT_BUFFERS); 869 if (!axi_data.bufnum1) { 870 pr_err("%s: pmem region lookup error\n", __func__); 871 return -EINVAL; 872 } 873 axi_data.region = ®ion[0]; 874 data = &axi_data; 875 break; 876 case CMD_GENERAL: 877 case CMD_STATS_DISABLE: 878 break; 879 default: 880 pr_err("%s: unknown command type %d\n", 881 __func__, cfgcmd.cmd_type); 882 return -EINVAL; 883 } 884 885 886 if (sync->vfefn.vfe_config) 887 rc = sync->vfefn.vfe_config(&cfgcmd, data); 888 889 return rc; 890} 891 892static int msm_frame_axi_cfg(struct msm_sync *sync, 893 struct msm_vfe_cfg_cmd *cfgcmd) 894{ 895 int rc = -EIO; 896 struct axidata axi_data; 897 void *data = &axi_data; 898 struct msm_pmem_region region[8]; 899 int pmem_type; 900 901 memset(&axi_data, 0, sizeof(axi_data)); 902 903 switch (cfgcmd->cmd_type) { 904 case CMD_AXI_CFG_OUT1: 905 pmem_type = MSM_PMEM_OUTPUT1; 906 axi_data.bufnum1 = 907 msm_pmem_region_lookup(&sync->frame, pmem_type, 908 ®ion[0], 8); 909 if (!axi_data.bufnum1) { 910 pr_err("%s: pmem region lookup error\n", __func__); 911 return -EINVAL; 912 } 913 break; 914 915 case CMD_AXI_CFG_OUT2: 916 pmem_type = MSM_PMEM_OUTPUT2; 917 axi_data.bufnum2 = 918 msm_pmem_region_lookup(&sync->frame, pmem_type, 919 ®ion[0], 8); 920 if (!axi_data.bufnum2) { 921 pr_err("%s: pmem region lookup error\n", __func__); 922 return -EINVAL; 923 } 924 break; 925 926 case CMD_AXI_CFG_SNAP_O1_AND_O2: 927 pmem_type = MSM_PMEM_THUMBAIL; 928 axi_data.bufnum1 = 929 msm_pmem_region_lookup(&sync->frame, pmem_type, 930 ®ion[0], 8); 931 if (!axi_data.bufnum1) { 932 pr_err("%s: pmem region lookup error\n", __func__); 933 return -EINVAL; 934 } 935 936 pmem_type = MSM_PMEM_MAINIMG; 937 axi_data.bufnum2 = 938 msm_pmem_region_lookup(&sync->frame, pmem_type, 939 ®ion[axi_data.bufnum1], 8); 940 if (!axi_data.bufnum2) { 941 pr_err("%s: pmem region lookup error\n", __func__); 942 return -EINVAL; 943 } 944 break; 945 946 case CMD_RAW_PICT_AXI_CFG: 947 pmem_type = MSM_PMEM_RAW_MAINIMG; 948 axi_data.bufnum2 = 949 msm_pmem_region_lookup(&sync->frame, pmem_type, 950 ®ion[0], 8); 951 if (!axi_data.bufnum2) { 952 pr_err("%s: pmem region lookup error\n", __func__); 953 return -EINVAL; 954 } 955 break; 956 957 case CMD_GENERAL: 958 data = NULL; 959 break; 960 961 default: 962 pr_err("%s: unknown command type %d\n", 963 __func__, cfgcmd->cmd_type); 964 return -EINVAL; 965 } 966 967 axi_data.region = ®ion[0]; 968 969 /* send the AXI configuration command to driver */ 970 if (sync->vfefn.vfe_config) 971 rc = sync->vfefn.vfe_config(cfgcmd, data); 972 973 return rc; 974} 975 976static int msm_get_sensor_info(struct msm_sync *sync, void __user *arg) 977{ 978 int rc = 0; 979 struct msm_camsensor_info info; 980 struct msm_camera_sensor_info *sdata; 981 982 if (copy_from_user(&info, 983 arg, 984 sizeof(struct msm_camsensor_info))) { 985 ERR_COPY_FROM_USER(); 986 return -EFAULT; 987 } 988 989 sdata = sync->pdev->dev.platform_data; 990 CDBG("sensor_name %s\n", sdata->sensor_name); 991 992 memcpy(&info.name[0], 993 sdata->sensor_name, 994 MAX_SENSOR_NAME); 995 info.flash_enabled = sdata->flash_type != MSM_CAMERA_FLASH_NONE; 996 997 /* copy back to user space */ 998 if (copy_to_user((void *)arg, 999 &info, 1000 sizeof(struct msm_camsensor_info))) { 1001 ERR_COPY_TO_USER(); 1002 rc = -EFAULT; 1003 } 1004 1005 return rc; 1006} 1007 1008static int __msm_put_frame_buf(struct msm_sync *sync, 1009 struct msm_frame *pb) 1010{ 1011 unsigned long pphy; 1012 struct msm_vfe_cfg_cmd cfgcmd; 1013 1014 int rc = -EIO; 1015 1016 pphy = msm_pmem_frame_vtop_lookup(sync, 1017 pb->buffer, 1018 pb->y_off, pb->cbcr_off, pb->fd); 1019 1020 if (pphy != 0) { 1021 CDBG("rel: vaddr = 0x%lx, paddr = 0x%lx\n", 1022 pb->buffer, pphy); 1023 cfgcmd.cmd_type = CMD_FRAME_BUF_RELEASE; 1024 cfgcmd.value = (void *)pb; 1025 if (sync->vfefn.vfe_config) 1026 rc = sync->vfefn.vfe_config(&cfgcmd, &pphy); 1027 } else { 1028 pr_err("%s: msm_pmem_frame_vtop_lookup failed\n", 1029 __func__); 1030 rc = -EINVAL; 1031 } 1032 1033 return rc; 1034} 1035 1036static int msm_put_frame_buffer(struct msm_sync *sync, void __user *arg) 1037{ 1038 struct msm_frame buf_t; 1039 1040 if (copy_from_user(&buf_t, 1041 arg, 1042 sizeof(struct msm_frame))) { 1043 ERR_COPY_FROM_USER(); 1044 return -EFAULT; 1045 } 1046 1047 return __msm_put_frame_buf(sync, &buf_t); 1048} 1049 1050static int __msm_register_pmem(struct msm_sync *sync, 1051 struct msm_pmem_info *pinfo) 1052{ 1053 int rc = 0; 1054 1055 switch (pinfo->type) { 1056 case MSM_PMEM_OUTPUT1: 1057 case MSM_PMEM_OUTPUT2: 1058 case MSM_PMEM_THUMBAIL: 1059 case MSM_PMEM_MAINIMG: 1060 case MSM_PMEM_RAW_MAINIMG: 1061 rc = msm_pmem_table_add(&sync->frame, pinfo); 1062 break; 1063 1064 case MSM_PMEM_AEC_AWB: 1065 case MSM_PMEM_AF: 1066 rc = msm_pmem_table_add(&sync->stats, pinfo); 1067 break; 1068 1069 default: 1070 rc = -EINVAL; 1071 break; 1072 } 1073 1074 return rc; 1075} 1076 1077static int msm_register_pmem(struct msm_sync *sync, void __user *arg) 1078{ 1079 struct msm_pmem_info info; 1080 1081 if (copy_from_user(&info, arg, sizeof(info))) { 1082 ERR_COPY_FROM_USER(); 1083 return -EFAULT; 1084 } 1085 1086 return __msm_register_pmem(sync, &info); 1087} 1088 1089static int msm_stats_axi_cfg(struct msm_sync *sync, 1090 struct msm_vfe_cfg_cmd *cfgcmd) 1091{ 1092 int rc = -EIO; 1093 struct axidata axi_data; 1094 void *data = &axi_data; 1095 1096 struct msm_pmem_region region[3]; 1097 int pmem_type = MSM_PMEM_MAX; 1098 1099 memset(&axi_data, 0, sizeof(axi_data)); 1100 1101 switch (cfgcmd->cmd_type) { 1102 case CMD_STATS_AXI_CFG: 1103 pmem_type = MSM_PMEM_AEC_AWB; 1104 break; 1105 case CMD_STATS_AF_AXI_CFG: 1106 pmem_type = MSM_PMEM_AF; 1107 break; 1108 case CMD_GENERAL: 1109 data = NULL; 1110 break; 1111 default: 1112 pr_err("%s: unknown command type %d\n", 1113 __func__, cfgcmd->cmd_type); 1114 return -EINVAL; 1115 } 1116 1117 if (cfgcmd->cmd_type != CMD_GENERAL) { 1118 axi_data.bufnum1 = 1119 msm_pmem_region_lookup(&sync->stats, pmem_type, 1120 ®ion[0], NUM_WB_EXP_STAT_OUTPUT_BUFFERS); 1121 if (!axi_data.bufnum1) { 1122 pr_err("%s: pmem region lookup error\n", __func__); 1123 return -EINVAL; 1124 } 1125 axi_data.region = ®ion[0]; 1126 } 1127 1128 /* send the AEC/AWB STATS configuration command to driver */ 1129 if (sync->vfefn.vfe_config) 1130 rc = sync->vfefn.vfe_config(cfgcmd, &axi_data); 1131 1132 return rc; 1133} 1134 1135static int msm_put_stats_buffer(struct msm_sync *sync, void __user *arg) 1136{ 1137 int rc = -EIO; 1138 1139 struct msm_stats_buf buf; 1140 unsigned long pphy; 1141 struct msm_vfe_cfg_cmd cfgcmd; 1142 1143 if (copy_from_user(&buf, arg, 1144 sizeof(struct msm_stats_buf))) { 1145 ERR_COPY_FROM_USER(); 1146 return -EFAULT; 1147 } 1148 1149 CDBG("msm_put_stats_buffer\n"); 1150 pphy = msm_pmem_stats_vtop_lookup(sync, buf.buffer, buf.fd); 1151 1152 if (pphy != 0) { 1153 if (buf.type == STAT_AEAW) 1154 cfgcmd.cmd_type = CMD_STATS_BUF_RELEASE; 1155 else if (buf.type == STAT_AF) 1156 cfgcmd.cmd_type = CMD_STATS_AF_BUF_RELEASE; 1157 else { 1158 pr_err("%s: invalid buf type %d\n", 1159 __func__, 1160 buf.type); 1161 rc = -EINVAL; 1162 goto put_done; 1163 } 1164 1165 cfgcmd.value = (void *)&buf; 1166 1167 if (sync->vfefn.vfe_config) { 1168 rc = sync->vfefn.vfe_config(&cfgcmd, &pphy); 1169 if (rc < 0) 1170 pr_err("msm_put_stats_buffer: "\ 1171 "vfe_config err %d\n", rc); 1172 } else 1173 pr_err("msm_put_stats_buffer: vfe_config is NULL\n"); 1174 } else { 1175 pr_err("msm_put_stats_buffer: NULL physical address\n"); 1176 rc = -EINVAL; 1177 } 1178 1179put_done: 1180 return rc; 1181} 1182 1183static int msm_axi_config(struct msm_sync *sync, void __user *arg) 1184{ 1185 struct msm_vfe_cfg_cmd cfgcmd; 1186 1187 if (copy_from_user(&cfgcmd, arg, sizeof(cfgcmd))) { 1188 ERR_COPY_FROM_USER(); 1189 return -EFAULT; 1190 } 1191 1192 switch (cfgcmd.cmd_type) { 1193 case CMD_AXI_CFG_OUT1: 1194 case CMD_AXI_CFG_OUT2: 1195 case CMD_AXI_CFG_SNAP_O1_AND_O2: 1196 case CMD_RAW_PICT_AXI_CFG: 1197 return msm_frame_axi_cfg(sync, &cfgcmd); 1198 1199 case CMD_STATS_AXI_CFG: 1200 case CMD_STATS_AF_AXI_CFG: 1201 return msm_stats_axi_cfg(sync, &cfgcmd); 1202 1203 default: 1204 pr_err("%s: unknown command type %d\n", 1205 __func__, 1206 cfgcmd.cmd_type); 1207 return -EINVAL; 1208 } 1209 1210 return 0; 1211} 1212 1213static int __msm_get_pic(struct msm_sync *sync, struct msm_ctrl_cmd *ctrl) 1214{ 1215 unsigned long flags; 1216 int rc = 0; 1217 int tm; 1218 1219 struct msm_queue_cmd *qcmd = NULL; 1220 1221 tm = (int)ctrl->timeout_ms; 1222 1223 rc = wait_event_interruptible_timeout( 1224 sync->pict_frame_wait, 1225 !list_empty_careful(&sync->pict_frame_q), 1226 msecs_to_jiffies(tm)); 1227 if (list_empty_careful(&sync->pict_frame_q)) { 1228 if (rc == 0) 1229 return -ETIMEDOUT; 1230 if (rc < 0) { 1231 pr_err("msm_camera_get_picture, rc = %d\n", rc); 1232 return rc; 1233 } 1234 } 1235 1236 spin_lock_irqsave(&sync->pict_frame_q_lock, flags); 1237 BUG_ON(list_empty(&sync->pict_frame_q)); 1238 qcmd = list_first_entry(&sync->pict_frame_q, 1239 struct msm_queue_cmd, list); 1240 list_del_init(&qcmd->list); 1241 spin_unlock_irqrestore(&sync->pict_frame_q_lock, flags); 1242 1243 if (qcmd->command != NULL) { 1244 struct msm_ctrl_cmd *q = 1245 (struct msm_ctrl_cmd *)qcmd->command; 1246 ctrl->type = q->type; 1247 ctrl->status = q->status; 1248 } else { 1249 ctrl->type = -1; 1250 ctrl->status = -1; 1251 } 1252 1253 kfree(qcmd); 1254 return rc; 1255} 1256 1257static int msm_get_pic(struct msm_sync *sync, void __user *arg) 1258{ 1259 struct msm_ctrl_cmd ctrlcmd_t; 1260 int rc; 1261 1262 if (copy_from_user(&ctrlcmd_t, 1263 arg, 1264 sizeof(struct msm_ctrl_cmd))) { 1265 ERR_COPY_FROM_USER(); 1266 return -EFAULT; 1267 } 1268 1269 rc = __msm_get_pic(sync, &ctrlcmd_t); 1270 if (rc < 0) 1271 return rc; 1272 1273 if (sync->croplen) { 1274 if (ctrlcmd_t.length < sync->croplen) { 1275 pr_err("msm_get_pic: invalid len %d\n", 1276 ctrlcmd_t.length); 1277 return -EINVAL; 1278 } 1279 if (copy_to_user(ctrlcmd_t.value, 1280 sync->cropinfo, 1281 sync->croplen)) { 1282 ERR_COPY_TO_USER(); 1283 return -EFAULT; 1284 } 1285 } 1286 1287 if (copy_to_user((void *)arg, 1288 &ctrlcmd_t, 1289 sizeof(struct msm_ctrl_cmd))) { 1290 ERR_COPY_TO_USER(); 1291 return -EFAULT; 1292 } 1293 return 0; 1294} 1295 1296static int msm_set_crop(struct msm_sync *sync, void __user *arg) 1297{ 1298 struct crop_info crop; 1299 1300 if (copy_from_user(&crop, 1301 arg, 1302 sizeof(struct crop_info))) { 1303 ERR_COPY_FROM_USER(); 1304 return -EFAULT; 1305 } 1306 1307 if (!sync->croplen) { 1308 sync->cropinfo = kmalloc(crop.len, GFP_KERNEL); 1309 if (!sync->cropinfo) 1310 return -ENOMEM; 1311 } else if (sync->croplen < crop.len) 1312 return -EINVAL; 1313 1314 if (copy_from_user(sync->cropinfo, 1315 crop.info, 1316 crop.len)) { 1317 ERR_COPY_FROM_USER(); 1318 kfree(sync->cropinfo); 1319 return -EFAULT; 1320 } 1321 1322 sync->croplen = crop.len; 1323 1324 return 0; 1325} 1326 1327static int msm_pict_pp_done(struct msm_sync *sync, void __user *arg) 1328{ 1329 struct msm_ctrl_cmd udata; 1330 struct msm_ctrl_cmd *ctrlcmd = NULL; 1331 struct msm_queue_cmd *qcmd = NULL; 1332 unsigned long flags; 1333 int rc = 0; 1334 1335 if (!sync->pict_pp) 1336 return -EINVAL; 1337 1338 if (copy_from_user(&udata, arg, sizeof(struct msm_ctrl_cmd))) { 1339 ERR_COPY_FROM_USER(); 1340 rc = -EFAULT; 1341 goto pp_fail; 1342 } 1343 1344 qcmd = kmalloc(sizeof(struct msm_queue_cmd) + 1345 sizeof(struct msm_ctrl_cmd), 1346 GFP_KERNEL); 1347 if (!qcmd) { 1348 rc = -ENOMEM; 1349 goto pp_fail; 1350 } 1351 1352 qcmd->type = MSM_CAM_Q_VFE_MSG; 1353 qcmd->command = ctrlcmd = (struct msm_ctrl_cmd *)(qcmd + 1); 1354 memset(ctrlcmd, 0, sizeof(struct msm_ctrl_cmd)); 1355 ctrlcmd->type = udata.type; 1356 ctrlcmd->status = udata.status; 1357 1358 spin_lock_irqsave(&sync->pict_frame_q_lock, flags); 1359 list_add_tail(&qcmd->list, &sync->pict_frame_q); 1360 spin_unlock_irqrestore(&sync->pict_frame_q_lock, flags); 1361 wake_up(&sync->pict_frame_wait); 1362 1363pp_fail: 1364 return rc; 1365} 1366 1367static long msm_ioctl_common(struct msm_device *pmsm, 1368 unsigned int cmd, 1369 void __user *argp) 1370{ 1371 CDBG("msm_ioctl_common\n"); 1372 switch (cmd) { 1373 case MSM_CAM_IOCTL_REGISTER_PMEM: 1374 return msm_register_pmem(pmsm->sync, argp); 1375 case MSM_CAM_IOCTL_UNREGISTER_PMEM: 1376 return msm_pmem_table_del(pmsm->sync, argp); 1377 default: 1378 return -EINVAL; 1379 } 1380} 1381 1382static long msm_ioctl_config(struct file *filep, unsigned int cmd, 1383 unsigned long arg) 1384{ 1385 int rc = -EINVAL; 1386 void __user *argp = (void __user *)arg; 1387 struct msm_device *pmsm = filep->private_data; 1388 1389 CDBG("msm_ioctl_config cmd = %d\n", _IOC_NR(cmd)); 1390 1391 switch (cmd) { 1392 case MSM_CAM_IOCTL_GET_SENSOR_INFO: 1393 rc = msm_get_sensor_info(pmsm->sync, argp); 1394 break; 1395 1396 case MSM_CAM_IOCTL_CONFIG_VFE: 1397 /* Coming from config thread for update */ 1398 rc = msm_config_vfe(pmsm->sync, argp); 1399 break; 1400 1401 case MSM_CAM_IOCTL_GET_STATS: 1402 /* Coming from config thread wait 1403 * for vfe statistics and control requests */ 1404 rc = msm_get_stats(pmsm->sync, argp); 1405 break; 1406 1407 case MSM_CAM_IOCTL_ENABLE_VFE: 1408 /* This request comes from control thread: 1409 * enable either QCAMTASK or VFETASK */ 1410 rc = msm_enable_vfe(pmsm->sync, argp); 1411 break; 1412 1413 case MSM_CAM_IOCTL_DISABLE_VFE: 1414 /* This request comes from control thread: 1415 * disable either QCAMTASK or VFETASK */ 1416 rc = msm_disable_vfe(pmsm->sync, argp); 1417 break; 1418 1419 case MSM_CAM_IOCTL_VFE_APPS_RESET: 1420 msm_camio_vfe_blk_reset(); 1421 rc = 0; 1422 break; 1423 1424 case MSM_CAM_IOCTL_RELEASE_STATS_BUFFER: 1425 rc = msm_put_stats_buffer(pmsm->sync, argp); 1426 break; 1427 1428 case MSM_CAM_IOCTL_AXI_CONFIG: 1429 rc = msm_axi_config(pmsm->sync, argp); 1430 break; 1431 1432 case MSM_CAM_IOCTL_SET_CROP: 1433 rc = msm_set_crop(pmsm->sync, argp); 1434 break; 1435 1436 case MSM_CAM_IOCTL_PICT_PP: { 1437 uint8_t enable; 1438 if (copy_from_user(&enable, argp, sizeof(enable))) { 1439 ERR_COPY_FROM_USER(); 1440 rc = -EFAULT; 1441 } else { 1442 pmsm->sync->pict_pp = enable; 1443 rc = 0; 1444 } 1445 break; 1446 } 1447 1448 case MSM_CAM_IOCTL_PICT_PP_DONE: 1449 rc = msm_pict_pp_done(pmsm->sync, argp); 1450 break; 1451 1452 case MSM_CAM_IOCTL_SENSOR_IO_CFG: 1453 rc = pmsm->sync->sctrl.s_config(argp); 1454 break; 1455 1456 case MSM_CAM_IOCTL_FLASH_LED_CFG: { 1457 uint32_t led_state; 1458 if (copy_from_user(&led_state, argp, sizeof(led_state))) { 1459 ERR_COPY_FROM_USER(); 1460 rc = -EFAULT; 1461 } else 1462 rc = msm_camera_flash_set_led_state(led_state); 1463 break; 1464 } 1465 1466 default: 1467 rc = msm_ioctl_common(pmsm, cmd, argp); 1468 break; 1469 } 1470 1471 CDBG("msm_ioctl_config cmd = %d DONE\n", _IOC_NR(cmd)); 1472 return rc; 1473} 1474 1475static int msm_unblock_poll_frame(struct msm_sync *); 1476 1477static long msm_ioctl_frame(struct file *filep, unsigned int cmd, 1478 unsigned long arg) 1479{ 1480 int rc = -EINVAL; 1481 void __user *argp = (void __user *)arg; 1482 struct msm_device *pmsm = filep->private_data; 1483 1484 1485 switch (cmd) { 1486 case MSM_CAM_IOCTL_GETFRAME: 1487 /* Coming from frame thread to get frame 1488 * after SELECT is done */ 1489 rc = msm_get_frame(pmsm->sync, argp); 1490 break; 1491 case MSM_CAM_IOCTL_RELEASE_FRAME_BUFFER: 1492 rc = msm_put_frame_buffer(pmsm->sync, argp); 1493 break; 1494 case MSM_CAM_IOCTL_UNBLOCK_POLL_FRAME: 1495 rc = msm_unblock_poll_frame(pmsm->sync); 1496 break; 1497 default: 1498 break; 1499 } 1500 1501 return rc; 1502} 1503 1504 1505static long msm_ioctl_control(struct file *filep, unsigned int cmd, 1506 unsigned long arg) 1507{ 1508 int rc = -EINVAL; 1509 void __user *argp = (void __user *)arg; 1510 struct msm_control_device *ctrl_pmsm = filep->private_data; 1511 struct msm_device *pmsm = ctrl_pmsm->pmsm; 1512 1513 switch (cmd) { 1514 case MSM_CAM_IOCTL_CTRL_COMMAND: 1515 /* Coming from control thread, may need to wait for 1516 * command status */ 1517 rc = msm_control(ctrl_pmsm, 1, argp); 1518 break; 1519 case MSM_CAM_IOCTL_CTRL_COMMAND_2: 1520 /* Sends a message, returns immediately */ 1521 rc = msm_control(ctrl_pmsm, 0, argp); 1522 break; 1523 case MSM_CAM_IOCTL_CTRL_CMD_DONE: 1524 /* Config thread calls the control thread to notify it 1525 * of the result of a MSM_CAM_IOCTL_CTRL_COMMAND. 1526 */ 1527 rc = msm_ctrl_cmd_done(ctrl_pmsm, argp); 1528 break; 1529 case MSM_CAM_IOCTL_GET_PICTURE: 1530 rc = msm_get_pic(pmsm->sync, argp); 1531 break; 1532 default: 1533 rc = msm_ioctl_common(pmsm, cmd, argp); 1534 break; 1535 } 1536 1537 return rc; 1538} 1539 1540static int __msm_release(struct msm_sync *sync) 1541{ 1542 struct msm_pmem_region *region; 1543 struct hlist_node *hnode; 1544 struct hlist_node *n; 1545 1546 mutex_lock(&sync->lock); 1547 if (sync->opencnt) 1548 sync->opencnt--; 1549 1550 if (!sync->opencnt) { 1551 /* need to clean up system resource */ 1552 if (sync->vfefn.vfe_release) 1553 sync->vfefn.vfe_release(sync->pdev); 1554 1555 if (sync->cropinfo) { 1556 kfree(sync->cropinfo); 1557 sync->cropinfo = NULL; 1558 sync->croplen = 0; 1559 } 1560 1561 hlist_for_each_entry_safe(region, hnode, n, 1562 &sync->frame, list) { 1563 hlist_del(hnode); 1564 put_pmem_file(region->file); 1565 kfree(region); 1566 } 1567 1568 hlist_for_each_entry_safe(region, hnode, n, 1569 &sync->stats, list) { 1570 hlist_del(hnode); 1571 put_pmem_file(region->file); 1572 kfree(region); 1573 } 1574 1575 MSM_DRAIN_QUEUE(sync, msg_event_q); 1576 MSM_DRAIN_QUEUE(sync, prev_frame_q); 1577 MSM_DRAIN_QUEUE(sync, pict_frame_q); 1578 1579 sync->sctrl.s_release(); 1580 1581 sync->apps_id = NULL; 1582 CDBG("msm_release completed!\n"); 1583 } 1584 mutex_unlock(&sync->lock); 1585 1586 return 0; 1587} 1588 1589static int msm_release_config(struct inode *node, struct file *filep) 1590{ 1591 int rc; 1592 struct msm_device *pmsm = filep->private_data; 1593 printk("msm_camera: RELEASE %s\n", filep->f_path.dentry->d_name.name); 1594 rc = __msm_release(pmsm->sync); 1595 atomic_set(&pmsm->opened, 0); 1596 return rc; 1597} 1598 1599static int msm_release_control(struct inode *node, struct file *filep) 1600{ 1601 int rc; 1602 struct msm_control_device *ctrl_pmsm = filep->private_data; 1603 struct msm_device *pmsm = ctrl_pmsm->pmsm; 1604 printk(KERN_INFO "msm_camera: RELEASE %s\n", 1605 filep->f_path.dentry->d_name.name); 1606 rc = __msm_release(pmsm->sync); 1607 if (!rc) { 1608 MSM_DRAIN_QUEUE(&ctrl_pmsm->ctrl_q, ctrl_status_q); 1609 MSM_DRAIN_QUEUE(pmsm->sync, pict_frame_q); 1610 } 1611 kfree(ctrl_pmsm); 1612 return rc; 1613} 1614 1615static int msm_release_frame(struct inode *node, struct file *filep) 1616{ 1617 int rc; 1618 struct msm_device *pmsm = filep->private_data; 1619 printk(KERN_INFO "msm_camera: RELEASE %s\n", 1620 filep->f_path.dentry->d_name.name); 1621 rc = __msm_release(pmsm->sync); 1622 if (!rc) { 1623 MSM_DRAIN_QUEUE(pmsm->sync, prev_frame_q); 1624 atomic_set(&pmsm->opened, 0); 1625 } 1626 return rc; 1627} 1628 1629static int msm_unblock_poll_frame(struct msm_sync *sync) 1630{ 1631 unsigned long flags; 1632 CDBG("msm_unblock_poll_frame\n"); 1633 spin_lock_irqsave(&sync->prev_frame_q_lock, flags); 1634 sync->unblock_poll_frame = 1; 1635 wake_up(&sync->prev_frame_wait); 1636 spin_unlock_irqrestore(&sync->prev_frame_q_lock, flags); 1637 return 0; 1638} 1639 1640static unsigned int __msm_poll_frame(struct msm_sync *sync, 1641 struct file *filep, 1642 struct poll_table_struct *pll_table) 1643{ 1644 int rc = 0; 1645 unsigned long flags; 1646 1647 poll_wait(filep, &sync->prev_frame_wait, pll_table); 1648 1649 spin_lock_irqsave(&sync->prev_frame_q_lock, flags); 1650 if (!list_empty_careful(&sync->prev_frame_q)) 1651 /* frame ready */ 1652 rc = POLLIN | POLLRDNORM; 1653 if (sync->unblock_poll_frame) { 1654 CDBG("%s: sync->unblock_poll_frame is true\n", __func__); 1655 rc |= POLLPRI; 1656 sync->unblock_poll_frame = 0; 1657 } 1658 spin_unlock_irqrestore(&sync->prev_frame_q_lock, flags); 1659 1660 return rc; 1661} 1662 1663static unsigned int msm_poll_frame(struct file *filep, 1664 struct poll_table_struct *pll_table) 1665{ 1666 struct msm_device *pmsm = filep->private_data; 1667 return __msm_poll_frame(pmsm->sync, filep, pll_table); 1668} 1669 1670/* 1671 * This function executes in interrupt context. 1672 */ 1673 1674static void *msm_vfe_sync_alloc(int size, 1675 void *syncdata __attribute__((unused))) 1676{ 1677 struct msm_queue_cmd *qcmd = 1678 kmalloc(sizeof(struct msm_queue_cmd) + size, GFP_ATOMIC); 1679 return qcmd ? qcmd + 1 : NULL; 1680} 1681 1682/* 1683 * This function executes in interrupt context. 1684 */ 1685 1686static void msm_vfe_sync(struct msm_vfe_resp *vdata, 1687 enum msm_queue qtype, void *syncdata) 1688{ 1689 struct msm_queue_cmd *qcmd = NULL; 1690 struct msm_queue_cmd *qcmd_frame = NULL; 1691 struct msm_vfe_phy_info *fphy; 1692 1693 unsigned long flags; 1694 struct msm_sync *sync = (struct msm_sync *)syncdata; 1695 if (!sync) { 1696 pr_err("msm_camera: no context in dsp callback.\n"); 1697 return; 1698 } 1699 1700 qcmd = ((struct msm_queue_cmd *)vdata) - 1; 1701 qcmd->type = qtype; 1702 1703 if (qtype == MSM_CAM_Q_VFE_MSG) { 1704 switch (vdata->type) { 1705 case VFE_MSG_OUTPUT1: 1706 case VFE_MSG_OUTPUT2: 1707 qcmd_frame = 1708 kmalloc(sizeof(struct msm_queue_cmd) + 1709 sizeof(struct msm_vfe_phy_info), 1710 GFP_ATOMIC); 1711 if (!qcmd_frame) 1712 goto mem_fail; 1713 fphy = (struct msm_vfe_phy_info *)(qcmd_frame + 1); 1714 *fphy = vdata->phy; 1715 1716 qcmd_frame->type = MSM_CAM_Q_VFE_MSG; 1717 qcmd_frame->command = fphy; 1718 1719 CDBG("qcmd_frame= 0x%x phy_y= 0x%x, phy_cbcr= 0x%x\n", 1720 (int) qcmd_frame, fphy->y_phy, fphy->cbcr_phy); 1721 1722 spin_lock_irqsave(&sync->prev_frame_q_lock, flags); 1723 list_add_tail(&qcmd_frame->list, &sync->prev_frame_q); 1724 wake_up(&sync->prev_frame_wait); 1725 spin_unlock_irqrestore(&sync->prev_frame_q_lock, flags); 1726 CDBG("woke up frame thread\n"); 1727 break; 1728 case VFE_MSG_SNAPSHOT: 1729 if (sync->pict_pp) 1730 break; 1731 1732 CDBG("snapshot pp = %d\n", sync->pict_pp); 1733 qcmd_frame = 1734 kmalloc(sizeof(struct msm_queue_cmd), 1735 GFP_ATOMIC); 1736 if (!qcmd_frame) 1737 goto mem_fail; 1738 qcmd_frame->type = MSM_CAM_Q_VFE_MSG; 1739 qcmd_frame->command = NULL; 1740 spin_lock_irqsave(&sync->pict_frame_q_lock, 1741 flags); 1742 list_add_tail(&qcmd_frame->list, &sync->pict_frame_q); 1743 wake_up(&sync->pict_frame_wait); 1744 spin_unlock_irqrestore(&sync->pict_frame_q_lock, flags); 1745 CDBG("woke up picture thread\n"); 1746 break; 1747 default: 1748 CDBG("%s: qtype = %d not handled\n", 1749 __func__, vdata->type); 1750 break; 1751 } 1752 } 1753 1754 qcmd->command = (void *)vdata; 1755 CDBG("vdata->type = %d\n", vdata->type); 1756 1757 spin_lock_irqsave(&sync->msg_event_q_lock, flags); 1758 list_add_tail(&qcmd->list, &sync->msg_event_q); 1759 wake_up(&sync->msg_event_wait); 1760 spin_unlock_irqrestore(&sync->msg_event_q_lock, flags); 1761 CDBG("woke up config thread\n"); 1762 return; 1763 1764mem_fail: 1765 kfree(qcmd); 1766} 1767 1768static struct msm_vfe_callback msm_vfe_s = { 1769 .vfe_resp = msm_vfe_sync, 1770 .vfe_alloc = msm_vfe_sync_alloc, 1771}; 1772 1773static int __msm_open(struct msm_sync *sync, const char *const apps_id) 1774{ 1775 int rc = 0; 1776 1777 mutex_lock(&sync->lock); 1778 if (sync->apps_id && strcmp(sync->apps_id, apps_id)) { 1779 pr_err("msm_camera(%s): sensor %s is already opened for %s\n", 1780 apps_id, 1781 sync->sdata->sensor_name, 1782 sync->apps_id); 1783 rc = -EBUSY; 1784 goto msm_open_done; 1785 } 1786 1787 sync->apps_id = apps_id; 1788 1789 if (!sync->opencnt) { 1790 1791 msm_camvfe_fn_init(&sync->vfefn, sync); 1792 if (sync->vfefn.vfe_init) { 1793 rc = sync->vfefn.vfe_init(&msm_vfe_s, 1794 sync->pdev); 1795 if (rc < 0) { 1796 pr_err("vfe_init failed at %d\n", rc); 1797 goto msm_open_done; 1798 } 1799 rc = sync->sctrl.s_init(sync->sdata); 1800 if (rc < 0) { 1801 pr_err("sensor init failed: %d\n", rc); 1802 goto msm_open_done; 1803 } 1804 } else { 1805 pr_err("no sensor init func\n"); 1806 rc = -ENODEV; 1807 goto msm_open_done; 1808 } 1809 1810 if (rc >= 0) { 1811 INIT_HLIST_HEAD(&sync->frame); 1812 INIT_HLIST_HEAD(&sync->stats); 1813 sync->unblock_poll_frame = 0; 1814 } 1815 } 1816 sync->opencnt++; 1817 1818msm_open_done: 1819 mutex_unlock(&sync->lock); 1820 return rc; 1821} 1822 1823static int msm_open_common(struct inode *inode, struct file *filep, 1824 int once) 1825{ 1826 int rc; 1827 struct msm_device *pmsm = 1828 container_of(inode->i_cdev, struct msm_device, cdev); 1829 1830 CDBG("msm_camera: open %s\n", filep->f_path.dentry->d_name.name); 1831 1832 if (atomic_cmpxchg(&pmsm->opened, 0, 1) && once) { 1833 pr_err("msm_camera: %s is already opened.\n", 1834 filep->f_path.dentry->d_name.name); 1835 return -EBUSY; 1836 } 1837 1838 rc = nonseekable_open(inode, filep); 1839 if (rc < 0) { 1840 pr_err("msm_open: nonseekable_open error %d\n", rc); 1841 return rc; 1842 } 1843 1844 rc = __msm_open(pmsm->sync, MSM_APPS_ID_PROP); 1845 if (rc < 0) 1846 return rc; 1847 1848 filep->private_data = pmsm; 1849 1850 CDBG("msm_open() open: rc = %d\n", rc); 1851 return rc; 1852} 1853 1854static int msm_open(struct inode *inode, struct file *filep) 1855{ 1856 return msm_open_common(inode, filep, 1); 1857} 1858 1859static int msm_open_control(struct inode *inode, struct file *filep) 1860{ 1861 int rc; 1862 1863 struct msm_control_device *ctrl_pmsm = 1864 kmalloc(sizeof(struct msm_control_device), GFP_KERNEL); 1865 if (!ctrl_pmsm) 1866 return -ENOMEM; 1867 1868 rc = msm_open_common(inode, filep, 0); 1869 if (rc < 0) { 1870 kfree(ctrl_pmsm); 1871 return rc; 1872 } 1873 1874 ctrl_pmsm->pmsm = filep->private_data; 1875 filep->private_data = ctrl_pmsm; 1876 spin_lock_init(&ctrl_pmsm->ctrl_q.ctrl_status_q_lock); 1877 INIT_LIST_HEAD(&ctrl_pmsm->ctrl_q.ctrl_status_q); 1878 init_waitqueue_head(&ctrl_pmsm->ctrl_q.ctrl_status_wait); 1879 1880 CDBG("msm_open() open: rc = %d\n", rc); 1881 return rc; 1882} 1883 1884static int __msm_v4l2_control(struct msm_sync *sync, 1885 struct msm_ctrl_cmd *out) 1886{ 1887 int rc = 0; 1888 1889 struct msm_queue_cmd *qcmd = NULL, *rcmd = NULL; 1890 struct msm_ctrl_cmd *ctrl; 1891 struct msm_control_device_queue FIXME; 1892 1893 /* wake up config thread, 4 is for V4L2 application */ 1894 qcmd = kmalloc(sizeof(struct msm_queue_cmd), GFP_KERNEL); 1895 if (!qcmd) { 1896 pr_err("msm_control: cannot allocate buffer\n"); 1897 rc = -ENOMEM; 1898 goto end; 1899 } 1900 qcmd->type = MSM_CAM_Q_V4L2_REQ; 1901 qcmd->command = out; 1902 1903 rcmd = __msm_control(sync, &FIXME, qcmd, out->timeout_ms); 1904 if (IS_ERR(rcmd)) { 1905 rc = PTR_ERR(rcmd); 1906 goto end; 1907 } 1908 1909 ctrl = (struct msm_ctrl_cmd *)(rcmd->command); 1910 BUG_ON(out->length < ctrl->length); 1911 memcpy(out->value, ctrl->value, ctrl->length); 1912 1913end: 1914 kfree(rcmd); 1915 CDBG("__msm_v4l2_control: end rc = %d\n", rc); 1916 return rc; 1917} 1918 1919static const struct file_operations msm_fops_config = { 1920 .owner = THIS_MODULE, 1921 .open = msm_open, 1922 .unlocked_ioctl = msm_ioctl_config, 1923 .release = msm_release_config, 1924}; 1925 1926static const struct file_operations msm_fops_control = { 1927 .owner = THIS_MODULE, 1928 .open = msm_open_control, 1929 .unlocked_ioctl = msm_ioctl_control, 1930 .release = msm_release_control, 1931}; 1932 1933static const struct file_operations msm_fops_frame = { 1934 .owner = THIS_MODULE, 1935 .open = msm_open, 1936 .unlocked_ioctl = msm_ioctl_frame, 1937 .release = msm_release_frame, 1938 .poll = msm_poll_frame, 1939}; 1940 1941static int msm_setup_cdev(struct msm_device *msm, 1942 int node, 1943 dev_t devno, 1944 const char *suffix, 1945 const struct file_operations *fops) 1946{ 1947 int rc = -ENODEV; 1948 1949 struct device *device = 1950 device_create(msm_class, NULL, 1951 devno, NULL, 1952 "%s%d", suffix, node); 1953 1954 if (IS_ERR(device)) { 1955 rc = PTR_ERR(device); 1956 pr_err("msm_camera: error creating device: %d\n", rc); 1957 return rc; 1958 } 1959 1960 cdev_init(&msm->cdev, fops); 1961 msm->cdev.owner = THIS_MODULE; 1962 1963 rc = cdev_add(&msm->cdev, devno, 1); 1964 if (rc < 0) { 1965 pr_err("msm_camera: error adding cdev: %d\n", rc); 1966 device_destroy(msm_class, devno); 1967 return rc; 1968 } 1969 1970 return rc; 1971} 1972 1973static int msm_tear_down_cdev(struct msm_device *msm, dev_t devno) 1974{ 1975 cdev_del(&msm->cdev); 1976 device_destroy(msm_class, devno); 1977 return 0; 1978} 1979 1980int msm_v4l2_register(struct msm_v4l2_driver *drv) 1981{ 1982 if (list_empty(&msm_sensors)) 1983 return -ENODEV; 1984 1985 drv->sync = list_first_entry(&msm_sensors, struct msm_sync, list); 1986 drv->open = __msm_open; 1987 drv->release = __msm_release; 1988 drv->ctrl = __msm_v4l2_control; 1989 drv->reg_pmem = __msm_register_pmem; 1990 drv->get_frame = __msm_get_frame; 1991 drv->put_frame = __msm_put_frame_buf; 1992 drv->get_pict = __msm_get_pic; 1993 drv->drv_poll = __msm_poll_frame; 1994 1995 return 0; 1996} 1997EXPORT_SYMBOL(msm_v4l2_register); 1998 1999int msm_v4l2_unregister(struct msm_v4l2_driver *drv) 2000{ 2001 drv->sync = NULL; 2002 return 0; 2003} 2004EXPORT_SYMBOL(msm_v4l2_unregister); 2005 2006static int msm_sync_init(struct msm_sync *sync, 2007 struct platform_device *pdev, 2008 int (*sensor_probe)(const struct msm_camera_sensor_info *, 2009 struct msm_sensor_ctrl *)) 2010{ 2011 int rc = 0; 2012 struct msm_sensor_ctrl sctrl; 2013 sync->sdata = pdev->dev.platform_data; 2014 2015 spin_lock_init(&sync->msg_event_q_lock); 2016 INIT_LIST_HEAD(&sync->msg_event_q); 2017 init_waitqueue_head(&sync->msg_event_wait); 2018 2019 spin_lock_init(&sync->prev_frame_q_lock); 2020 INIT_LIST_HEAD(&sync->prev_frame_q); 2021 init_waitqueue_head(&sync->prev_frame_wait); 2022 2023 spin_lock_init(&sync->pict_frame_q_lock); 2024 INIT_LIST_HEAD(&sync->pict_frame_q); 2025 init_waitqueue_head(&sync->pict_frame_wait); 2026 2027 rc = msm_camio_probe_on(pdev); 2028 if (rc < 0) 2029 return rc; 2030 rc = sensor_probe(sync->sdata, &sctrl); 2031 if (rc >= 0) { 2032 sync->pdev = pdev; 2033 sync->sctrl = sctrl; 2034 } 2035 msm_camio_probe_off(pdev); 2036 if (rc < 0) { 2037 pr_err("msm_camera: failed to initialize %s\n", 2038 sync->sdata->sensor_name); 2039 return rc; 2040 } 2041 2042 sync->opencnt = 0; 2043 mutex_init(&sync->lock); 2044 CDBG("initialized %s\n", sync->sdata->sensor_name); 2045 return rc; 2046} 2047 2048static int msm_sync_destroy(struct msm_sync *sync) 2049{ 2050 return 0; 2051} 2052 2053static int msm_device_init(struct msm_device *pmsm, 2054 struct msm_sync *sync, 2055 int node) 2056{ 2057 int dev_num = 3 * node; 2058 int rc = msm_setup_cdev(pmsm, node, 2059 MKDEV(MAJOR(msm_devno), dev_num), 2060 "control", &msm_fops_control); 2061 if (rc < 0) { 2062 pr_err("error creating control node: %d\n", rc); 2063 return rc; 2064 } 2065 2066 rc = msm_setup_cdev(pmsm + 1, node, 2067 MKDEV(MAJOR(msm_devno), dev_num + 1), 2068 "config", &msm_fops_config); 2069 if (rc < 0) { 2070 pr_err("error creating config node: %d\n", rc); 2071 msm_tear_down_cdev(pmsm, MKDEV(MAJOR(msm_devno), 2072 dev_num)); 2073 return rc; 2074 } 2075 2076 rc = msm_setup_cdev(pmsm + 2, node, 2077 MKDEV(MAJOR(msm_devno), dev_num + 2), 2078 "frame", &msm_fops_frame); 2079 if (rc < 0) { 2080 pr_err("error creating frame node: %d\n", rc); 2081 msm_tear_down_cdev(pmsm, 2082 MKDEV(MAJOR(msm_devno), dev_num)); 2083 msm_tear_down_cdev(pmsm + 1, 2084 MKDEV(MAJOR(msm_devno), dev_num + 1)); 2085 return rc; 2086 } 2087 2088 atomic_set(&pmsm[0].opened, 0); 2089 atomic_set(&pmsm[1].opened, 0); 2090 atomic_set(&pmsm[2].opened, 0); 2091 2092 pmsm[0].sync = sync; 2093 pmsm[1].sync = sync; 2094 pmsm[2].sync = sync; 2095 2096 return rc; 2097} 2098 2099int msm_camera_drv_start(struct platform_device *dev, 2100 int (*sensor_probe)(const struct msm_camera_sensor_info *, 2101 struct msm_sensor_ctrl *)) 2102{ 2103 struct msm_device *pmsm = NULL; 2104 struct msm_sync *sync; 2105 int rc = -ENODEV; 2106 static int camera_node; 2107 2108 if (camera_node >= MSM_MAX_CAMERA_SENSORS) { 2109 pr_err("msm_camera: too many camera sensors\n"); 2110 return rc; 2111 } 2112 2113 if (!msm_class) { 2114 /* There are three device nodes per sensor */ 2115 rc = alloc_chrdev_region(&msm_devno, 0, 2116 3 * MSM_MAX_CAMERA_SENSORS, 2117 "msm_camera"); 2118 if (rc < 0) { 2119 pr_err("msm_camera: failed to allocate chrdev: %d\n", 2120 rc); 2121 return rc; 2122 } 2123 2124 msm_class = class_create(THIS_MODULE, "msm_camera"); 2125 if (IS_ERR(msm_class)) { 2126 rc = PTR_ERR(msm_class); 2127 pr_err("msm_camera: create device class failed: %d\n", 2128 rc); 2129 return rc; 2130 } 2131 } 2132 2133 pmsm = kzalloc(sizeof(struct msm_device) * 3 + 2134 sizeof(struct msm_sync), GFP_ATOMIC); 2135 if (!pmsm) 2136 return -ENOMEM; 2137 sync = (struct msm_sync *)(pmsm + 3); 2138 2139 rc = msm_sync_init(sync, dev, sensor_probe); 2140 if (rc < 0) { 2141 kfree(pmsm); 2142 return rc; 2143 } 2144 2145 CDBG("setting camera node %d\n", camera_node); 2146 rc = msm_device_init(pmsm, sync, camera_node); 2147 if (rc < 0) { 2148 msm_sync_destroy(sync); 2149 kfree(pmsm); 2150 return rc; 2151 } 2152 2153 camera_node++; 2154 list_add(&sync->list, &msm_sensors); 2155 return rc; 2156} 2157EXPORT_SYMBOL(msm_camera_drv_start); 2158