camss-vfe.c (38862B)
1// SPDX-License-Identifier: GPL-2.0 2/* 3 * camss-vfe.c 4 * 5 * Qualcomm MSM Camera Subsystem - VFE (Video Front End) Module 6 * 7 * Copyright (c) 2013-2015, The Linux Foundation. All rights reserved. 8 * Copyright (C) 2015-2018 Linaro Ltd. 9 */ 10#include <linux/clk.h> 11#include <linux/completion.h> 12#include <linux/interrupt.h> 13#include <linux/iommu.h> 14#include <linux/mutex.h> 15#include <linux/of.h> 16#include <linux/platform_device.h> 17#include <linux/pm_runtime.h> 18#include <linux/spinlock_types.h> 19#include <linux/spinlock.h> 20#include <media/media-entity.h> 21#include <media/v4l2-device.h> 22#include <media/v4l2-subdev.h> 23 24#include "camss-vfe.h" 25#include "camss.h" 26 27#define MSM_VFE_NAME "msm_vfe" 28 29/* VFE reset timeout */ 30#define VFE_RESET_TIMEOUT_MS 50 31 32#define SCALER_RATIO_MAX 16 33 34struct vfe_format { 35 u32 code; 36 u8 bpp; 37}; 38 39static const struct vfe_format formats_rdi_8x16[] = { 40 { MEDIA_BUS_FMT_UYVY8_2X8, 8 }, 41 { MEDIA_BUS_FMT_VYUY8_2X8, 8 }, 42 { MEDIA_BUS_FMT_YUYV8_2X8, 8 }, 43 { MEDIA_BUS_FMT_YVYU8_2X8, 8 }, 44 { MEDIA_BUS_FMT_SBGGR8_1X8, 8 }, 45 { MEDIA_BUS_FMT_SGBRG8_1X8, 8 }, 46 { MEDIA_BUS_FMT_SGRBG8_1X8, 8 }, 47 { MEDIA_BUS_FMT_SRGGB8_1X8, 8 }, 48 { MEDIA_BUS_FMT_SBGGR10_1X10, 10 }, 49 { MEDIA_BUS_FMT_SGBRG10_1X10, 10 }, 50 { MEDIA_BUS_FMT_SGRBG10_1X10, 10 }, 51 { MEDIA_BUS_FMT_SRGGB10_1X10, 10 }, 52 { MEDIA_BUS_FMT_SBGGR12_1X12, 12 }, 53 { MEDIA_BUS_FMT_SGBRG12_1X12, 12 }, 54 { MEDIA_BUS_FMT_SGRBG12_1X12, 12 }, 55 { MEDIA_BUS_FMT_SRGGB12_1X12, 12 }, 56 { MEDIA_BUS_FMT_Y10_1X10, 10 }, 57}; 58 59static const struct vfe_format formats_pix_8x16[] = { 60 { MEDIA_BUS_FMT_UYVY8_2X8, 8 }, 61 { MEDIA_BUS_FMT_VYUY8_2X8, 8 }, 62 { MEDIA_BUS_FMT_YUYV8_2X8, 8 }, 63 { MEDIA_BUS_FMT_YVYU8_2X8, 8 }, 64}; 65 66static const struct vfe_format formats_rdi_8x96[] = { 67 { MEDIA_BUS_FMT_UYVY8_2X8, 8 }, 68 { MEDIA_BUS_FMT_VYUY8_2X8, 8 }, 69 { MEDIA_BUS_FMT_YUYV8_2X8, 8 }, 70 { MEDIA_BUS_FMT_YVYU8_2X8, 8 }, 71 { MEDIA_BUS_FMT_SBGGR8_1X8, 8 }, 72 { MEDIA_BUS_FMT_SGBRG8_1X8, 8 }, 73 { MEDIA_BUS_FMT_SGRBG8_1X8, 8 }, 74 { MEDIA_BUS_FMT_SRGGB8_1X8, 8 }, 75 { MEDIA_BUS_FMT_SBGGR10_1X10, 10 }, 76 { MEDIA_BUS_FMT_SGBRG10_1X10, 10 }, 77 { MEDIA_BUS_FMT_SGRBG10_1X10, 10 }, 78 { MEDIA_BUS_FMT_SRGGB10_1X10, 10 }, 79 { MEDIA_BUS_FMT_SBGGR10_2X8_PADHI_LE, 16 }, 80 { MEDIA_BUS_FMT_SBGGR12_1X12, 12 }, 81 { MEDIA_BUS_FMT_SGBRG12_1X12, 12 }, 82 { MEDIA_BUS_FMT_SGRBG12_1X12, 12 }, 83 { MEDIA_BUS_FMT_SRGGB12_1X12, 12 }, 84 { MEDIA_BUS_FMT_SBGGR14_1X14, 14 }, 85 { MEDIA_BUS_FMT_SGBRG14_1X14, 14 }, 86 { MEDIA_BUS_FMT_SGRBG14_1X14, 14 }, 87 { MEDIA_BUS_FMT_SRGGB14_1X14, 14 }, 88 { MEDIA_BUS_FMT_Y10_1X10, 10 }, 89 { MEDIA_BUS_FMT_Y10_2X8_PADHI_LE, 16 }, 90}; 91 92static const struct vfe_format formats_pix_8x96[] = { 93 { MEDIA_BUS_FMT_UYVY8_2X8, 8 }, 94 { MEDIA_BUS_FMT_VYUY8_2X8, 8 }, 95 { MEDIA_BUS_FMT_YUYV8_2X8, 8 }, 96 { MEDIA_BUS_FMT_YVYU8_2X8, 8 }, 97}; 98 99static const struct vfe_format formats_rdi_845[] = { 100 { MEDIA_BUS_FMT_UYVY8_2X8, 8 }, 101 { MEDIA_BUS_FMT_VYUY8_2X8, 8 }, 102 { MEDIA_BUS_FMT_YUYV8_2X8, 8 }, 103 { MEDIA_BUS_FMT_YVYU8_2X8, 8 }, 104 { MEDIA_BUS_FMT_SBGGR8_1X8, 8 }, 105 { MEDIA_BUS_FMT_SGBRG8_1X8, 8 }, 106 { MEDIA_BUS_FMT_SGRBG8_1X8, 8 }, 107 { MEDIA_BUS_FMT_SRGGB8_1X8, 8 }, 108 { MEDIA_BUS_FMT_SBGGR10_1X10, 10 }, 109 { MEDIA_BUS_FMT_SGBRG10_1X10, 10 }, 110 { MEDIA_BUS_FMT_SGRBG10_1X10, 10 }, 111 { MEDIA_BUS_FMT_SRGGB10_1X10, 10 }, 112 { MEDIA_BUS_FMT_SBGGR10_2X8_PADHI_LE, 16 }, 113 { MEDIA_BUS_FMT_SBGGR12_1X12, 12 }, 114 { MEDIA_BUS_FMT_SGBRG12_1X12, 12 }, 115 { MEDIA_BUS_FMT_SGRBG12_1X12, 12 }, 116 { MEDIA_BUS_FMT_SRGGB12_1X12, 12 }, 117 { MEDIA_BUS_FMT_SBGGR14_1X14, 14 }, 118 { MEDIA_BUS_FMT_SGBRG14_1X14, 14 }, 119 { MEDIA_BUS_FMT_SGRBG14_1X14, 14 }, 120 { MEDIA_BUS_FMT_SRGGB14_1X14, 14 }, 121 { MEDIA_BUS_FMT_Y8_1X8, 8 }, 122 { MEDIA_BUS_FMT_Y10_1X10, 10 }, 123 { MEDIA_BUS_FMT_Y10_2X8_PADHI_LE, 16 }, 124}; 125 126/* 127 * vfe_get_bpp - map media bus format to bits per pixel 128 * @formats: supported media bus formats array 129 * @nformats: size of @formats array 130 * @code: media bus format code 131 * 132 * Return number of bits per pixel 133 */ 134static u8 vfe_get_bpp(const struct vfe_format *formats, 135 unsigned int nformats, u32 code) 136{ 137 unsigned int i; 138 139 for (i = 0; i < nformats; i++) 140 if (code == formats[i].code) 141 return formats[i].bpp; 142 143 WARN(1, "Unknown format\n"); 144 145 return formats[0].bpp; 146} 147 148static u32 vfe_find_code(u32 *code, unsigned int n_code, 149 unsigned int index, u32 req_code) 150{ 151 int i; 152 153 if (!req_code && (index >= n_code)) 154 return 0; 155 156 for (i = 0; i < n_code; i++) 157 if (req_code) { 158 if (req_code == code[i]) 159 return req_code; 160 } else { 161 if (i == index) 162 return code[i]; 163 } 164 165 return code[0]; 166} 167 168static u32 vfe_src_pad_code(struct vfe_line *line, u32 sink_code, 169 unsigned int index, u32 src_req_code) 170{ 171 struct vfe_device *vfe = to_vfe(line); 172 173 if (vfe->camss->version == CAMSS_8x16) 174 switch (sink_code) { 175 case MEDIA_BUS_FMT_YUYV8_2X8: 176 { 177 u32 src_code[] = { 178 MEDIA_BUS_FMT_YUYV8_2X8, 179 MEDIA_BUS_FMT_YUYV8_1_5X8, 180 }; 181 182 return vfe_find_code(src_code, ARRAY_SIZE(src_code), 183 index, src_req_code); 184 } 185 case MEDIA_BUS_FMT_YVYU8_2X8: 186 { 187 u32 src_code[] = { 188 MEDIA_BUS_FMT_YVYU8_2X8, 189 MEDIA_BUS_FMT_YVYU8_1_5X8, 190 }; 191 192 return vfe_find_code(src_code, ARRAY_SIZE(src_code), 193 index, src_req_code); 194 } 195 case MEDIA_BUS_FMT_UYVY8_2X8: 196 { 197 u32 src_code[] = { 198 MEDIA_BUS_FMT_UYVY8_2X8, 199 MEDIA_BUS_FMT_UYVY8_1_5X8, 200 }; 201 202 return vfe_find_code(src_code, ARRAY_SIZE(src_code), 203 index, src_req_code); 204 } 205 case MEDIA_BUS_FMT_VYUY8_2X8: 206 { 207 u32 src_code[] = { 208 MEDIA_BUS_FMT_VYUY8_2X8, 209 MEDIA_BUS_FMT_VYUY8_1_5X8, 210 }; 211 212 return vfe_find_code(src_code, ARRAY_SIZE(src_code), 213 index, src_req_code); 214 } 215 default: 216 if (index > 0) 217 return 0; 218 219 return sink_code; 220 } 221 else if (vfe->camss->version == CAMSS_8x96 || 222 vfe->camss->version == CAMSS_660 || 223 vfe->camss->version == CAMSS_845 || 224 vfe->camss->version == CAMSS_8250) 225 switch (sink_code) { 226 case MEDIA_BUS_FMT_YUYV8_2X8: 227 { 228 u32 src_code[] = { 229 MEDIA_BUS_FMT_YUYV8_2X8, 230 MEDIA_BUS_FMT_YVYU8_2X8, 231 MEDIA_BUS_FMT_UYVY8_2X8, 232 MEDIA_BUS_FMT_VYUY8_2X8, 233 MEDIA_BUS_FMT_YUYV8_1_5X8, 234 }; 235 236 return vfe_find_code(src_code, ARRAY_SIZE(src_code), 237 index, src_req_code); 238 } 239 case MEDIA_BUS_FMT_YVYU8_2X8: 240 { 241 u32 src_code[] = { 242 MEDIA_BUS_FMT_YVYU8_2X8, 243 MEDIA_BUS_FMT_YUYV8_2X8, 244 MEDIA_BUS_FMT_UYVY8_2X8, 245 MEDIA_BUS_FMT_VYUY8_2X8, 246 MEDIA_BUS_FMT_YVYU8_1_5X8, 247 }; 248 249 return vfe_find_code(src_code, ARRAY_SIZE(src_code), 250 index, src_req_code); 251 } 252 case MEDIA_BUS_FMT_UYVY8_2X8: 253 { 254 u32 src_code[] = { 255 MEDIA_BUS_FMT_UYVY8_2X8, 256 MEDIA_BUS_FMT_YUYV8_2X8, 257 MEDIA_BUS_FMT_YVYU8_2X8, 258 MEDIA_BUS_FMT_VYUY8_2X8, 259 MEDIA_BUS_FMT_UYVY8_1_5X8, 260 }; 261 262 return vfe_find_code(src_code, ARRAY_SIZE(src_code), 263 index, src_req_code); 264 } 265 case MEDIA_BUS_FMT_VYUY8_2X8: 266 { 267 u32 src_code[] = { 268 MEDIA_BUS_FMT_VYUY8_2X8, 269 MEDIA_BUS_FMT_YUYV8_2X8, 270 MEDIA_BUS_FMT_YVYU8_2X8, 271 MEDIA_BUS_FMT_UYVY8_2X8, 272 MEDIA_BUS_FMT_VYUY8_1_5X8, 273 }; 274 275 return vfe_find_code(src_code, ARRAY_SIZE(src_code), 276 index, src_req_code); 277 } 278 default: 279 if (index > 0) 280 return 0; 281 282 return sink_code; 283 } 284 else 285 return 0; 286} 287 288int vfe_reset(struct vfe_device *vfe) 289{ 290 unsigned long time; 291 292 reinit_completion(&vfe->reset_complete); 293 294 vfe->ops->global_reset(vfe); 295 296 time = wait_for_completion_timeout(&vfe->reset_complete, 297 msecs_to_jiffies(VFE_RESET_TIMEOUT_MS)); 298 if (!time) { 299 dev_err(vfe->camss->dev, "VFE reset timeout\n"); 300 return -EIO; 301 } 302 303 return 0; 304} 305 306static void vfe_init_outputs(struct vfe_device *vfe) 307{ 308 int i; 309 310 for (i = 0; i < vfe->line_num; i++) { 311 struct vfe_output *output = &vfe->line[i].output; 312 313 output->state = VFE_OUTPUT_OFF; 314 output->buf[0] = NULL; 315 output->buf[1] = NULL; 316 INIT_LIST_HEAD(&output->pending_bufs); 317 } 318} 319 320static void vfe_reset_output_maps(struct vfe_device *vfe) 321{ 322 int i; 323 324 for (i = 0; i < ARRAY_SIZE(vfe->wm_output_map); i++) 325 vfe->wm_output_map[i] = VFE_LINE_NONE; 326} 327 328int vfe_reserve_wm(struct vfe_device *vfe, enum vfe_line_id line_id) 329{ 330 int ret = -EBUSY; 331 int i; 332 333 for (i = 0; i < ARRAY_SIZE(vfe->wm_output_map); i++) { 334 if (vfe->wm_output_map[i] == VFE_LINE_NONE) { 335 vfe->wm_output_map[i] = line_id; 336 ret = i; 337 break; 338 } 339 } 340 341 return ret; 342} 343 344int vfe_release_wm(struct vfe_device *vfe, u8 wm) 345{ 346 if (wm >= ARRAY_SIZE(vfe->wm_output_map)) 347 return -EINVAL; 348 349 vfe->wm_output_map[wm] = VFE_LINE_NONE; 350 351 return 0; 352} 353 354struct camss_buffer *vfe_buf_get_pending(struct vfe_output *output) 355{ 356 struct camss_buffer *buffer = NULL; 357 358 if (!list_empty(&output->pending_bufs)) { 359 buffer = list_first_entry(&output->pending_bufs, 360 struct camss_buffer, 361 queue); 362 list_del(&buffer->queue); 363 } 364 365 return buffer; 366} 367 368void vfe_buf_add_pending(struct vfe_output *output, 369 struct camss_buffer *buffer) 370{ 371 INIT_LIST_HEAD(&buffer->queue); 372 list_add_tail(&buffer->queue, &output->pending_bufs); 373} 374 375/* 376 * vfe_buf_flush_pending - Flush all pending buffers. 377 * @output: VFE output 378 * @state: vb2 buffer state 379 */ 380static void vfe_buf_flush_pending(struct vfe_output *output, 381 enum vb2_buffer_state state) 382{ 383 struct camss_buffer *buf; 384 struct camss_buffer *t; 385 386 list_for_each_entry_safe(buf, t, &output->pending_bufs, queue) { 387 vb2_buffer_done(&buf->vb.vb2_buf, state); 388 list_del(&buf->queue); 389 } 390} 391 392int vfe_put_output(struct vfe_line *line) 393{ 394 struct vfe_device *vfe = to_vfe(line); 395 struct vfe_output *output = &line->output; 396 unsigned long flags; 397 unsigned int i; 398 399 spin_lock_irqsave(&vfe->output_lock, flags); 400 401 for (i = 0; i < output->wm_num; i++) 402 vfe_release_wm(vfe, output->wm_idx[i]); 403 404 output->state = VFE_OUTPUT_OFF; 405 406 spin_unlock_irqrestore(&vfe->output_lock, flags); 407 return 0; 408} 409 410/** 411 * vfe_isr_comp_done() - Process composite image done interrupt 412 * @vfe: VFE Device 413 * @comp: Composite image id 414 */ 415void vfe_isr_comp_done(struct vfe_device *vfe, u8 comp) 416{ 417 unsigned int i; 418 419 for (i = 0; i < ARRAY_SIZE(vfe->wm_output_map); i++) 420 if (vfe->wm_output_map[i] == VFE_LINE_PIX) { 421 vfe->isr_ops.wm_done(vfe, i); 422 break; 423 } 424} 425 426void vfe_isr_reset_ack(struct vfe_device *vfe) 427{ 428 complete(&vfe->reset_complete); 429} 430 431/* 432 * vfe_set_clock_rates - Calculate and set clock rates on VFE module 433 * @vfe: VFE device 434 * 435 * Return 0 on success or a negative error code otherwise 436 */ 437static int vfe_set_clock_rates(struct vfe_device *vfe) 438{ 439 struct device *dev = vfe->camss->dev; 440 u64 pixel_clock[VFE_LINE_NUM_MAX]; 441 int i, j; 442 int ret; 443 444 for (i = VFE_LINE_RDI0; i < vfe->line_num; i++) { 445 ret = camss_get_pixel_clock(&vfe->line[i].subdev.entity, 446 &pixel_clock[i]); 447 if (ret) 448 pixel_clock[i] = 0; 449 } 450 451 for (i = 0; i < vfe->nclocks; i++) { 452 struct camss_clock *clock = &vfe->clock[i]; 453 454 if (!strcmp(clock->name, "vfe0") || 455 !strcmp(clock->name, "vfe1") || 456 !strcmp(clock->name, "vfe_lite")) { 457 u64 min_rate = 0; 458 long rate; 459 460 for (j = VFE_LINE_RDI0; j < vfe->line_num; j++) { 461 u32 tmp; 462 u8 bpp; 463 464 if (j == VFE_LINE_PIX) { 465 tmp = pixel_clock[j]; 466 } else { 467 struct vfe_line *l = &vfe->line[j]; 468 469 bpp = vfe_get_bpp(l->formats, 470 l->nformats, 471 l->fmt[MSM_VFE_PAD_SINK].code); 472 tmp = pixel_clock[j] * bpp / 64; 473 } 474 475 if (min_rate < tmp) 476 min_rate = tmp; 477 } 478 479 camss_add_clock_margin(&min_rate); 480 481 for (j = 0; j < clock->nfreqs; j++) 482 if (min_rate < clock->freq[j]) 483 break; 484 485 if (j == clock->nfreqs) { 486 dev_err(dev, 487 "Pixel clock is too high for VFE"); 488 return -EINVAL; 489 } 490 491 /* if sensor pixel clock is not available */ 492 /* set highest possible VFE clock rate */ 493 if (min_rate == 0) 494 j = clock->nfreqs - 1; 495 496 rate = clk_round_rate(clock->clk, clock->freq[j]); 497 if (rate < 0) { 498 dev_err(dev, "clk round rate failed: %ld\n", 499 rate); 500 return -EINVAL; 501 } 502 503 ret = clk_set_rate(clock->clk, rate); 504 if (ret < 0) { 505 dev_err(dev, "clk set rate failed: %d\n", ret); 506 return ret; 507 } 508 } 509 } 510 511 return 0; 512} 513 514/* 515 * vfe_check_clock_rates - Check current clock rates on VFE module 516 * @vfe: VFE device 517 * 518 * Return 0 if current clock rates are suitable for a new pipeline 519 * or a negative error code otherwise 520 */ 521static int vfe_check_clock_rates(struct vfe_device *vfe) 522{ 523 u64 pixel_clock[VFE_LINE_NUM_MAX]; 524 int i, j; 525 int ret; 526 527 for (i = VFE_LINE_RDI0; i < vfe->line_num; i++) { 528 ret = camss_get_pixel_clock(&vfe->line[i].subdev.entity, 529 &pixel_clock[i]); 530 if (ret) 531 pixel_clock[i] = 0; 532 } 533 534 for (i = 0; i < vfe->nclocks; i++) { 535 struct camss_clock *clock = &vfe->clock[i]; 536 537 if (!strcmp(clock->name, "vfe0") || 538 !strcmp(clock->name, "vfe1")) { 539 u64 min_rate = 0; 540 unsigned long rate; 541 542 for (j = VFE_LINE_RDI0; j < vfe->line_num; j++) { 543 u32 tmp; 544 u8 bpp; 545 546 if (j == VFE_LINE_PIX) { 547 tmp = pixel_clock[j]; 548 } else { 549 struct vfe_line *l = &vfe->line[j]; 550 551 bpp = vfe_get_bpp(l->formats, 552 l->nformats, 553 l->fmt[MSM_VFE_PAD_SINK].code); 554 tmp = pixel_clock[j] * bpp / 64; 555 } 556 557 if (min_rate < tmp) 558 min_rate = tmp; 559 } 560 561 camss_add_clock_margin(&min_rate); 562 563 rate = clk_get_rate(clock->clk); 564 if (rate < min_rate) 565 return -EBUSY; 566 } 567 } 568 569 return 0; 570} 571 572/* 573 * vfe_get - Power up and reset VFE module 574 * @vfe: VFE Device 575 * 576 * Return 0 on success or a negative error code otherwise 577 */ 578int vfe_get(struct vfe_device *vfe) 579{ 580 int ret; 581 582 mutex_lock(&vfe->power_lock); 583 584 if (vfe->power_count == 0) { 585 ret = vfe->ops->pm_domain_on(vfe); 586 if (ret < 0) 587 goto error_pm_domain; 588 589 ret = pm_runtime_resume_and_get(vfe->camss->dev); 590 if (ret < 0) 591 goto error_domain_off; 592 593 ret = vfe_set_clock_rates(vfe); 594 if (ret < 0) 595 goto error_pm_runtime_get; 596 597 ret = camss_enable_clocks(vfe->nclocks, vfe->clock, 598 vfe->camss->dev); 599 if (ret < 0) 600 goto error_pm_runtime_get; 601 602 ret = vfe_reset(vfe); 603 if (ret < 0) 604 goto error_reset; 605 606 vfe_reset_output_maps(vfe); 607 608 vfe_init_outputs(vfe); 609 610 vfe->ops->hw_version(vfe); 611 } else { 612 ret = vfe_check_clock_rates(vfe); 613 if (ret < 0) 614 goto error_pm_runtime_get; 615 } 616 vfe->power_count++; 617 618 mutex_unlock(&vfe->power_lock); 619 620 return 0; 621 622error_reset: 623 camss_disable_clocks(vfe->nclocks, vfe->clock); 624 625error_pm_runtime_get: 626 pm_runtime_put_sync(vfe->camss->dev); 627error_domain_off: 628 vfe->ops->pm_domain_off(vfe); 629 630error_pm_domain: 631 mutex_unlock(&vfe->power_lock); 632 633 return ret; 634} 635 636/* 637 * vfe_put - Power down VFE module 638 * @vfe: VFE Device 639 */ 640void vfe_put(struct vfe_device *vfe) 641{ 642 mutex_lock(&vfe->power_lock); 643 644 if (vfe->power_count == 0) { 645 dev_err(vfe->camss->dev, "vfe power off on power_count == 0\n"); 646 goto exit; 647 } else if (vfe->power_count == 1) { 648 if (vfe->was_streaming) { 649 vfe->was_streaming = 0; 650 vfe->ops->vfe_halt(vfe); 651 } 652 camss_disable_clocks(vfe->nclocks, vfe->clock); 653 pm_runtime_put_sync(vfe->camss->dev); 654 vfe->ops->pm_domain_off(vfe); 655 } 656 657 vfe->power_count--; 658 659exit: 660 mutex_unlock(&vfe->power_lock); 661} 662 663/* 664 * vfe_flush_buffers - Return all vb2 buffers 665 * @vid: Video device structure 666 * @state: vb2 buffer state of the returned buffers 667 * 668 * Return all buffers to vb2. This includes queued pending buffers (still 669 * unused) and any buffers given to the hardware but again still not used. 670 * 671 * Return 0 on success or a negative error code otherwise 672 */ 673int vfe_flush_buffers(struct camss_video *vid, 674 enum vb2_buffer_state state) 675{ 676 struct vfe_line *line = container_of(vid, struct vfe_line, video_out); 677 struct vfe_device *vfe = to_vfe(line); 678 struct vfe_output *output; 679 unsigned long flags; 680 681 output = &line->output; 682 683 spin_lock_irqsave(&vfe->output_lock, flags); 684 685 vfe_buf_flush_pending(output, state); 686 687 if (output->buf[0]) 688 vb2_buffer_done(&output->buf[0]->vb.vb2_buf, state); 689 690 if (output->buf[1]) 691 vb2_buffer_done(&output->buf[1]->vb.vb2_buf, state); 692 693 if (output->last_buffer) { 694 vb2_buffer_done(&output->last_buffer->vb.vb2_buf, state); 695 output->last_buffer = NULL; 696 } 697 698 spin_unlock_irqrestore(&vfe->output_lock, flags); 699 700 return 0; 701} 702 703/* 704 * vfe_set_power - Power on/off VFE module 705 * @sd: VFE V4L2 subdevice 706 * @on: Requested power state 707 * 708 * Return 0 on success or a negative error code otherwise 709 */ 710static int vfe_set_power(struct v4l2_subdev *sd, int on) 711{ 712 struct vfe_line *line = v4l2_get_subdevdata(sd); 713 struct vfe_device *vfe = to_vfe(line); 714 int ret; 715 716 if (on) { 717 ret = vfe_get(vfe); 718 if (ret < 0) 719 return ret; 720 } else { 721 vfe_put(vfe); 722 } 723 724 return 0; 725} 726 727/* 728 * vfe_set_stream - Enable/disable streaming on VFE module 729 * @sd: VFE V4L2 subdevice 730 * @enable: Requested streaming state 731 * 732 * Main configuration of VFE module is triggered here. 733 * 734 * Return 0 on success or a negative error code otherwise 735 */ 736static int vfe_set_stream(struct v4l2_subdev *sd, int enable) 737{ 738 struct vfe_line *line = v4l2_get_subdevdata(sd); 739 struct vfe_device *vfe = to_vfe(line); 740 int ret; 741 742 if (enable) { 743 ret = vfe->ops->vfe_enable(line); 744 if (ret < 0) 745 dev_err(vfe->camss->dev, 746 "Failed to enable vfe outputs\n"); 747 } else { 748 ret = vfe->ops->vfe_disable(line); 749 if (ret < 0) 750 dev_err(vfe->camss->dev, 751 "Failed to disable vfe outputs\n"); 752 } 753 754 return ret; 755} 756 757/* 758 * __vfe_get_format - Get pointer to format structure 759 * @line: VFE line 760 * @cfg: V4L2 subdev pad configuration 761 * @pad: pad from which format is requested 762 * @which: TRY or ACTIVE format 763 * 764 * Return pointer to TRY or ACTIVE format structure 765 */ 766static struct v4l2_mbus_framefmt * 767__vfe_get_format(struct vfe_line *line, 768 struct v4l2_subdev_state *sd_state, 769 unsigned int pad, 770 enum v4l2_subdev_format_whence which) 771{ 772 if (which == V4L2_SUBDEV_FORMAT_TRY) 773 return v4l2_subdev_get_try_format(&line->subdev, sd_state, 774 pad); 775 776 return &line->fmt[pad]; 777} 778 779/* 780 * __vfe_get_compose - Get pointer to compose selection structure 781 * @line: VFE line 782 * @cfg: V4L2 subdev pad configuration 783 * @which: TRY or ACTIVE format 784 * 785 * Return pointer to TRY or ACTIVE compose rectangle structure 786 */ 787static struct v4l2_rect * 788__vfe_get_compose(struct vfe_line *line, 789 struct v4l2_subdev_state *sd_state, 790 enum v4l2_subdev_format_whence which) 791{ 792 if (which == V4L2_SUBDEV_FORMAT_TRY) 793 return v4l2_subdev_get_try_compose(&line->subdev, sd_state, 794 MSM_VFE_PAD_SINK); 795 796 return &line->compose; 797} 798 799/* 800 * __vfe_get_crop - Get pointer to crop selection structure 801 * @line: VFE line 802 * @cfg: V4L2 subdev pad configuration 803 * @which: TRY or ACTIVE format 804 * 805 * Return pointer to TRY or ACTIVE crop rectangle structure 806 */ 807static struct v4l2_rect * 808__vfe_get_crop(struct vfe_line *line, 809 struct v4l2_subdev_state *sd_state, 810 enum v4l2_subdev_format_whence which) 811{ 812 if (which == V4L2_SUBDEV_FORMAT_TRY) 813 return v4l2_subdev_get_try_crop(&line->subdev, sd_state, 814 MSM_VFE_PAD_SRC); 815 816 return &line->crop; 817} 818 819/* 820 * vfe_try_format - Handle try format by pad subdev method 821 * @line: VFE line 822 * @cfg: V4L2 subdev pad configuration 823 * @pad: pad on which format is requested 824 * @fmt: pointer to v4l2 format structure 825 * @which: wanted subdev format 826 */ 827static void vfe_try_format(struct vfe_line *line, 828 struct v4l2_subdev_state *sd_state, 829 unsigned int pad, 830 struct v4l2_mbus_framefmt *fmt, 831 enum v4l2_subdev_format_whence which) 832{ 833 unsigned int i; 834 u32 code; 835 836 switch (pad) { 837 case MSM_VFE_PAD_SINK: 838 /* Set format on sink pad */ 839 840 for (i = 0; i < line->nformats; i++) 841 if (fmt->code == line->formats[i].code) 842 break; 843 844 /* If not found, use UYVY as default */ 845 if (i >= line->nformats) 846 fmt->code = MEDIA_BUS_FMT_UYVY8_2X8; 847 848 fmt->width = clamp_t(u32, fmt->width, 1, 8191); 849 fmt->height = clamp_t(u32, fmt->height, 1, 8191); 850 851 fmt->field = V4L2_FIELD_NONE; 852 fmt->colorspace = V4L2_COLORSPACE_SRGB; 853 854 break; 855 856 case MSM_VFE_PAD_SRC: 857 /* Set and return a format same as sink pad */ 858 code = fmt->code; 859 860 *fmt = *__vfe_get_format(line, sd_state, MSM_VFE_PAD_SINK, 861 which); 862 863 fmt->code = vfe_src_pad_code(line, fmt->code, 0, code); 864 865 if (line->id == VFE_LINE_PIX) { 866 struct v4l2_rect *rect; 867 868 rect = __vfe_get_crop(line, sd_state, which); 869 870 fmt->width = rect->width; 871 fmt->height = rect->height; 872 } 873 874 break; 875 } 876 877 fmt->colorspace = V4L2_COLORSPACE_SRGB; 878} 879 880/* 881 * vfe_try_compose - Handle try compose selection by pad subdev method 882 * @line: VFE line 883 * @cfg: V4L2 subdev pad configuration 884 * @rect: pointer to v4l2 rect structure 885 * @which: wanted subdev format 886 */ 887static void vfe_try_compose(struct vfe_line *line, 888 struct v4l2_subdev_state *sd_state, 889 struct v4l2_rect *rect, 890 enum v4l2_subdev_format_whence which) 891{ 892 struct v4l2_mbus_framefmt *fmt; 893 894 fmt = __vfe_get_format(line, sd_state, MSM_VFE_PAD_SINK, which); 895 896 if (rect->width > fmt->width) 897 rect->width = fmt->width; 898 899 if (rect->height > fmt->height) 900 rect->height = fmt->height; 901 902 if (fmt->width > rect->width * SCALER_RATIO_MAX) 903 rect->width = (fmt->width + SCALER_RATIO_MAX - 1) / 904 SCALER_RATIO_MAX; 905 906 rect->width &= ~0x1; 907 908 if (fmt->height > rect->height * SCALER_RATIO_MAX) 909 rect->height = (fmt->height + SCALER_RATIO_MAX - 1) / 910 SCALER_RATIO_MAX; 911 912 if (rect->width < 16) 913 rect->width = 16; 914 915 if (rect->height < 4) 916 rect->height = 4; 917} 918 919/* 920 * vfe_try_crop - Handle try crop selection by pad subdev method 921 * @line: VFE line 922 * @cfg: V4L2 subdev pad configuration 923 * @rect: pointer to v4l2 rect structure 924 * @which: wanted subdev format 925 */ 926static void vfe_try_crop(struct vfe_line *line, 927 struct v4l2_subdev_state *sd_state, 928 struct v4l2_rect *rect, 929 enum v4l2_subdev_format_whence which) 930{ 931 struct v4l2_rect *compose; 932 933 compose = __vfe_get_compose(line, sd_state, which); 934 935 if (rect->width > compose->width) 936 rect->width = compose->width; 937 938 if (rect->width + rect->left > compose->width) 939 rect->left = compose->width - rect->width; 940 941 if (rect->height > compose->height) 942 rect->height = compose->height; 943 944 if (rect->height + rect->top > compose->height) 945 rect->top = compose->height - rect->height; 946 947 /* wm in line based mode writes multiple of 16 horizontally */ 948 rect->left += (rect->width & 0xf) >> 1; 949 rect->width &= ~0xf; 950 951 if (rect->width < 16) { 952 rect->left = 0; 953 rect->width = 16; 954 } 955 956 if (rect->height < 4) { 957 rect->top = 0; 958 rect->height = 4; 959 } 960} 961 962/* 963 * vfe_enum_mbus_code - Handle pixel format enumeration 964 * @sd: VFE V4L2 subdevice 965 * @cfg: V4L2 subdev pad configuration 966 * @code: pointer to v4l2_subdev_mbus_code_enum structure 967 * 968 * return -EINVAL or zero on success 969 */ 970static int vfe_enum_mbus_code(struct v4l2_subdev *sd, 971 struct v4l2_subdev_state *sd_state, 972 struct v4l2_subdev_mbus_code_enum *code) 973{ 974 struct vfe_line *line = v4l2_get_subdevdata(sd); 975 976 if (code->pad == MSM_VFE_PAD_SINK) { 977 if (code->index >= line->nformats) 978 return -EINVAL; 979 980 code->code = line->formats[code->index].code; 981 } else { 982 struct v4l2_mbus_framefmt *sink_fmt; 983 984 sink_fmt = __vfe_get_format(line, sd_state, MSM_VFE_PAD_SINK, 985 code->which); 986 987 code->code = vfe_src_pad_code(line, sink_fmt->code, 988 code->index, 0); 989 if (!code->code) 990 return -EINVAL; 991 } 992 993 return 0; 994} 995 996/* 997 * vfe_enum_frame_size - Handle frame size enumeration 998 * @sd: VFE V4L2 subdevice 999 * @cfg: V4L2 subdev pad configuration 1000 * @fse: pointer to v4l2_subdev_frame_size_enum structure 1001 * 1002 * Return -EINVAL or zero on success 1003 */ 1004static int vfe_enum_frame_size(struct v4l2_subdev *sd, 1005 struct v4l2_subdev_state *sd_state, 1006 struct v4l2_subdev_frame_size_enum *fse) 1007{ 1008 struct vfe_line *line = v4l2_get_subdevdata(sd); 1009 struct v4l2_mbus_framefmt format; 1010 1011 if (fse->index != 0) 1012 return -EINVAL; 1013 1014 format.code = fse->code; 1015 format.width = 1; 1016 format.height = 1; 1017 vfe_try_format(line, sd_state, fse->pad, &format, fse->which); 1018 fse->min_width = format.width; 1019 fse->min_height = format.height; 1020 1021 if (format.code != fse->code) 1022 return -EINVAL; 1023 1024 format.code = fse->code; 1025 format.width = -1; 1026 format.height = -1; 1027 vfe_try_format(line, sd_state, fse->pad, &format, fse->which); 1028 fse->max_width = format.width; 1029 fse->max_height = format.height; 1030 1031 return 0; 1032} 1033 1034/* 1035 * vfe_get_format - Handle get format by pads subdev method 1036 * @sd: VFE V4L2 subdevice 1037 * @cfg: V4L2 subdev pad configuration 1038 * @fmt: pointer to v4l2 subdev format structure 1039 * 1040 * Return -EINVAL or zero on success 1041 */ 1042static int vfe_get_format(struct v4l2_subdev *sd, 1043 struct v4l2_subdev_state *sd_state, 1044 struct v4l2_subdev_format *fmt) 1045{ 1046 struct vfe_line *line = v4l2_get_subdevdata(sd); 1047 struct v4l2_mbus_framefmt *format; 1048 1049 format = __vfe_get_format(line, sd_state, fmt->pad, fmt->which); 1050 if (format == NULL) 1051 return -EINVAL; 1052 1053 fmt->format = *format; 1054 1055 return 0; 1056} 1057 1058static int vfe_set_selection(struct v4l2_subdev *sd, 1059 struct v4l2_subdev_state *sd_state, 1060 struct v4l2_subdev_selection *sel); 1061 1062/* 1063 * vfe_set_format - Handle set format by pads subdev method 1064 * @sd: VFE V4L2 subdevice 1065 * @cfg: V4L2 subdev pad configuration 1066 * @fmt: pointer to v4l2 subdev format structure 1067 * 1068 * Return -EINVAL or zero on success 1069 */ 1070static int vfe_set_format(struct v4l2_subdev *sd, 1071 struct v4l2_subdev_state *sd_state, 1072 struct v4l2_subdev_format *fmt) 1073{ 1074 struct vfe_line *line = v4l2_get_subdevdata(sd); 1075 struct v4l2_mbus_framefmt *format; 1076 1077 format = __vfe_get_format(line, sd_state, fmt->pad, fmt->which); 1078 if (format == NULL) 1079 return -EINVAL; 1080 1081 vfe_try_format(line, sd_state, fmt->pad, &fmt->format, fmt->which); 1082 *format = fmt->format; 1083 1084 if (fmt->pad == MSM_VFE_PAD_SINK) { 1085 struct v4l2_subdev_selection sel = { 0 }; 1086 int ret; 1087 1088 /* Propagate the format from sink to source */ 1089 format = __vfe_get_format(line, sd_state, MSM_VFE_PAD_SRC, 1090 fmt->which); 1091 1092 *format = fmt->format; 1093 vfe_try_format(line, sd_state, MSM_VFE_PAD_SRC, format, 1094 fmt->which); 1095 1096 if (line->id != VFE_LINE_PIX) 1097 return 0; 1098 1099 /* Reset sink pad compose selection */ 1100 sel.which = fmt->which; 1101 sel.pad = MSM_VFE_PAD_SINK; 1102 sel.target = V4L2_SEL_TGT_COMPOSE; 1103 sel.r.width = fmt->format.width; 1104 sel.r.height = fmt->format.height; 1105 ret = vfe_set_selection(sd, sd_state, &sel); 1106 if (ret < 0) 1107 return ret; 1108 } 1109 1110 return 0; 1111} 1112 1113/* 1114 * vfe_get_selection - Handle get selection by pads subdev method 1115 * @sd: VFE V4L2 subdevice 1116 * @cfg: V4L2 subdev pad configuration 1117 * @sel: pointer to v4l2 subdev selection structure 1118 * 1119 * Return -EINVAL or zero on success 1120 */ 1121static int vfe_get_selection(struct v4l2_subdev *sd, 1122 struct v4l2_subdev_state *sd_state, 1123 struct v4l2_subdev_selection *sel) 1124{ 1125 struct vfe_line *line = v4l2_get_subdevdata(sd); 1126 struct v4l2_subdev_format fmt = { 0 }; 1127 struct v4l2_rect *rect; 1128 int ret; 1129 1130 if (line->id != VFE_LINE_PIX) 1131 return -EINVAL; 1132 1133 if (sel->pad == MSM_VFE_PAD_SINK) 1134 switch (sel->target) { 1135 case V4L2_SEL_TGT_COMPOSE_BOUNDS: 1136 fmt.pad = sel->pad; 1137 fmt.which = sel->which; 1138 ret = vfe_get_format(sd, sd_state, &fmt); 1139 if (ret < 0) 1140 return ret; 1141 1142 sel->r.left = 0; 1143 sel->r.top = 0; 1144 sel->r.width = fmt.format.width; 1145 sel->r.height = fmt.format.height; 1146 break; 1147 case V4L2_SEL_TGT_COMPOSE: 1148 rect = __vfe_get_compose(line, sd_state, sel->which); 1149 if (rect == NULL) 1150 return -EINVAL; 1151 1152 sel->r = *rect; 1153 break; 1154 default: 1155 return -EINVAL; 1156 } 1157 else if (sel->pad == MSM_VFE_PAD_SRC) 1158 switch (sel->target) { 1159 case V4L2_SEL_TGT_CROP_BOUNDS: 1160 rect = __vfe_get_compose(line, sd_state, sel->which); 1161 if (rect == NULL) 1162 return -EINVAL; 1163 1164 sel->r.left = rect->left; 1165 sel->r.top = rect->top; 1166 sel->r.width = rect->width; 1167 sel->r.height = rect->height; 1168 break; 1169 case V4L2_SEL_TGT_CROP: 1170 rect = __vfe_get_crop(line, sd_state, sel->which); 1171 if (rect == NULL) 1172 return -EINVAL; 1173 1174 sel->r = *rect; 1175 break; 1176 default: 1177 return -EINVAL; 1178 } 1179 1180 return 0; 1181} 1182 1183/* 1184 * vfe_set_selection - Handle set selection by pads subdev method 1185 * @sd: VFE V4L2 subdevice 1186 * @cfg: V4L2 subdev pad configuration 1187 * @sel: pointer to v4l2 subdev selection structure 1188 * 1189 * Return -EINVAL or zero on success 1190 */ 1191static int vfe_set_selection(struct v4l2_subdev *sd, 1192 struct v4l2_subdev_state *sd_state, 1193 struct v4l2_subdev_selection *sel) 1194{ 1195 struct vfe_line *line = v4l2_get_subdevdata(sd); 1196 struct v4l2_rect *rect; 1197 int ret; 1198 1199 if (line->id != VFE_LINE_PIX) 1200 return -EINVAL; 1201 1202 if (sel->target == V4L2_SEL_TGT_COMPOSE && 1203 sel->pad == MSM_VFE_PAD_SINK) { 1204 struct v4l2_subdev_selection crop = { 0 }; 1205 1206 rect = __vfe_get_compose(line, sd_state, sel->which); 1207 if (rect == NULL) 1208 return -EINVAL; 1209 1210 vfe_try_compose(line, sd_state, &sel->r, sel->which); 1211 *rect = sel->r; 1212 1213 /* Reset source crop selection */ 1214 crop.which = sel->which; 1215 crop.pad = MSM_VFE_PAD_SRC; 1216 crop.target = V4L2_SEL_TGT_CROP; 1217 crop.r = *rect; 1218 ret = vfe_set_selection(sd, sd_state, &crop); 1219 } else if (sel->target == V4L2_SEL_TGT_CROP && 1220 sel->pad == MSM_VFE_PAD_SRC) { 1221 struct v4l2_subdev_format fmt = { 0 }; 1222 1223 rect = __vfe_get_crop(line, sd_state, sel->which); 1224 if (rect == NULL) 1225 return -EINVAL; 1226 1227 vfe_try_crop(line, sd_state, &sel->r, sel->which); 1228 *rect = sel->r; 1229 1230 /* Reset source pad format width and height */ 1231 fmt.which = sel->which; 1232 fmt.pad = MSM_VFE_PAD_SRC; 1233 ret = vfe_get_format(sd, sd_state, &fmt); 1234 if (ret < 0) 1235 return ret; 1236 1237 fmt.format.width = rect->width; 1238 fmt.format.height = rect->height; 1239 ret = vfe_set_format(sd, sd_state, &fmt); 1240 } else { 1241 ret = -EINVAL; 1242 } 1243 1244 return ret; 1245} 1246 1247/* 1248 * vfe_init_formats - Initialize formats on all pads 1249 * @sd: VFE V4L2 subdevice 1250 * @fh: V4L2 subdev file handle 1251 * 1252 * Initialize all pad formats with default values. 1253 * 1254 * Return 0 on success or a negative error code otherwise 1255 */ 1256static int vfe_init_formats(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) 1257{ 1258 struct v4l2_subdev_format format = { 1259 .pad = MSM_VFE_PAD_SINK, 1260 .which = fh ? V4L2_SUBDEV_FORMAT_TRY : 1261 V4L2_SUBDEV_FORMAT_ACTIVE, 1262 .format = { 1263 .code = MEDIA_BUS_FMT_UYVY8_2X8, 1264 .width = 1920, 1265 .height = 1080 1266 } 1267 }; 1268 1269 return vfe_set_format(sd, fh ? fh->state : NULL, &format); 1270} 1271 1272/* 1273 * msm_vfe_subdev_init - Initialize VFE device structure and resources 1274 * @vfe: VFE device 1275 * @res: VFE module resources table 1276 * 1277 * Return 0 on success or a negative error code otherwise 1278 */ 1279int msm_vfe_subdev_init(struct camss *camss, struct vfe_device *vfe, 1280 const struct resources *res, u8 id) 1281{ 1282 struct device *dev = camss->dev; 1283 struct platform_device *pdev = to_platform_device(dev); 1284 int i, j; 1285 int ret; 1286 1287 switch (camss->version) { 1288 case CAMSS_8x16: 1289 vfe->ops = &vfe_ops_4_1; 1290 break; 1291 case CAMSS_8x96: 1292 vfe->ops = &vfe_ops_4_7; 1293 break; 1294 case CAMSS_660: 1295 vfe->ops = &vfe_ops_4_8; 1296 break; 1297 case CAMSS_845: 1298 vfe->ops = &vfe_ops_170; 1299 break; 1300 case CAMSS_8250: 1301 vfe->ops = &vfe_ops_480; 1302 break; 1303 default: 1304 return -EINVAL; 1305 } 1306 vfe->ops->subdev_init(dev, vfe); 1307 1308 /* Memory */ 1309 1310 vfe->base = devm_platform_ioremap_resource_byname(pdev, res->reg[0]); 1311 if (IS_ERR(vfe->base)) { 1312 dev_err(dev, "could not map memory\n"); 1313 return PTR_ERR(vfe->base); 1314 } 1315 1316 /* Interrupt */ 1317 1318 ret = platform_get_irq_byname(pdev, res->interrupt[0]); 1319 if (ret < 0) 1320 return ret; 1321 1322 vfe->irq = ret; 1323 snprintf(vfe->irq_name, sizeof(vfe->irq_name), "%s_%s%d", 1324 dev_name(dev), MSM_VFE_NAME, id); 1325 ret = devm_request_irq(dev, vfe->irq, vfe->ops->isr, 1326 IRQF_TRIGGER_RISING, vfe->irq_name, vfe); 1327 if (ret < 0) { 1328 dev_err(dev, "request_irq failed: %d\n", ret); 1329 return ret; 1330 } 1331 1332 /* Clocks */ 1333 1334 vfe->nclocks = 0; 1335 while (res->clock[vfe->nclocks]) 1336 vfe->nclocks++; 1337 1338 vfe->clock = devm_kcalloc(dev, vfe->nclocks, sizeof(*vfe->clock), 1339 GFP_KERNEL); 1340 if (!vfe->clock) 1341 return -ENOMEM; 1342 1343 for (i = 0; i < vfe->nclocks; i++) { 1344 struct camss_clock *clock = &vfe->clock[i]; 1345 1346 clock->clk = devm_clk_get(dev, res->clock[i]); 1347 if (IS_ERR(clock->clk)) 1348 return PTR_ERR(clock->clk); 1349 1350 clock->name = res->clock[i]; 1351 1352 clock->nfreqs = 0; 1353 while (res->clock_rate[i][clock->nfreqs]) 1354 clock->nfreqs++; 1355 1356 if (!clock->nfreqs) { 1357 clock->freq = NULL; 1358 continue; 1359 } 1360 1361 clock->freq = devm_kcalloc(dev, 1362 clock->nfreqs, 1363 sizeof(*clock->freq), 1364 GFP_KERNEL); 1365 if (!clock->freq) 1366 return -ENOMEM; 1367 1368 for (j = 0; j < clock->nfreqs; j++) 1369 clock->freq[j] = res->clock_rate[i][j]; 1370 } 1371 1372 mutex_init(&vfe->power_lock); 1373 vfe->power_count = 0; 1374 1375 mutex_init(&vfe->stream_lock); 1376 vfe->stream_count = 0; 1377 1378 spin_lock_init(&vfe->output_lock); 1379 1380 vfe->camss = camss; 1381 vfe->id = id; 1382 vfe->reg_update = 0; 1383 1384 for (i = VFE_LINE_RDI0; i < vfe->line_num; i++) { 1385 struct vfe_line *l = &vfe->line[i]; 1386 1387 l->video_out.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; 1388 l->video_out.camss = camss; 1389 l->id = i; 1390 init_completion(&l->output.sof); 1391 init_completion(&l->output.reg_update); 1392 1393 if (camss->version == CAMSS_8x16) { 1394 if (i == VFE_LINE_PIX) { 1395 l->formats = formats_pix_8x16; 1396 l->nformats = ARRAY_SIZE(formats_pix_8x16); 1397 } else { 1398 l->formats = formats_rdi_8x16; 1399 l->nformats = ARRAY_SIZE(formats_rdi_8x16); 1400 } 1401 } else if (camss->version == CAMSS_8x96 || 1402 camss->version == CAMSS_660) { 1403 if (i == VFE_LINE_PIX) { 1404 l->formats = formats_pix_8x96; 1405 l->nformats = ARRAY_SIZE(formats_pix_8x96); 1406 } else { 1407 l->formats = formats_rdi_8x96; 1408 l->nformats = ARRAY_SIZE(formats_rdi_8x96); 1409 } 1410 } else if (camss->version == CAMSS_845 || 1411 camss->version == CAMSS_8250) { 1412 l->formats = formats_rdi_845; 1413 l->nformats = ARRAY_SIZE(formats_rdi_845); 1414 } else { 1415 return -EINVAL; 1416 } 1417 } 1418 1419 init_completion(&vfe->reset_complete); 1420 init_completion(&vfe->halt_complete); 1421 1422 return 0; 1423} 1424 1425/* 1426 * msm_vfe_get_vfe_id - Get VFE HW module id 1427 * @entity: Pointer to VFE media entity structure 1428 * @id: Return CSID HW module id here 1429 */ 1430void msm_vfe_get_vfe_id(struct media_entity *entity, u8 *id) 1431{ 1432 struct v4l2_subdev *sd; 1433 struct vfe_line *line; 1434 struct vfe_device *vfe; 1435 1436 sd = media_entity_to_v4l2_subdev(entity); 1437 line = v4l2_get_subdevdata(sd); 1438 vfe = to_vfe(line); 1439 1440 *id = vfe->id; 1441} 1442 1443/* 1444 * msm_vfe_get_vfe_line_id - Get VFE line id by media entity 1445 * @entity: Pointer to VFE media entity structure 1446 * @id: Return VFE line id here 1447 */ 1448void msm_vfe_get_vfe_line_id(struct media_entity *entity, enum vfe_line_id *id) 1449{ 1450 struct v4l2_subdev *sd; 1451 struct vfe_line *line; 1452 1453 sd = media_entity_to_v4l2_subdev(entity); 1454 line = v4l2_get_subdevdata(sd); 1455 1456 *id = line->id; 1457} 1458 1459/* 1460 * vfe_link_setup - Setup VFE connections 1461 * @entity: Pointer to media entity structure 1462 * @local: Pointer to local pad 1463 * @remote: Pointer to remote pad 1464 * @flags: Link flags 1465 * 1466 * Return 0 on success 1467 */ 1468static int vfe_link_setup(struct media_entity *entity, 1469 const struct media_pad *local, 1470 const struct media_pad *remote, u32 flags) 1471{ 1472 if (flags & MEDIA_LNK_FL_ENABLED) 1473 if (media_entity_remote_pad(local)) 1474 return -EBUSY; 1475 1476 return 0; 1477} 1478 1479static const struct v4l2_subdev_core_ops vfe_core_ops = { 1480 .s_power = vfe_set_power, 1481}; 1482 1483static const struct v4l2_subdev_video_ops vfe_video_ops = { 1484 .s_stream = vfe_set_stream, 1485}; 1486 1487static const struct v4l2_subdev_pad_ops vfe_pad_ops = { 1488 .enum_mbus_code = vfe_enum_mbus_code, 1489 .enum_frame_size = vfe_enum_frame_size, 1490 .get_fmt = vfe_get_format, 1491 .set_fmt = vfe_set_format, 1492 .get_selection = vfe_get_selection, 1493 .set_selection = vfe_set_selection, 1494}; 1495 1496static const struct v4l2_subdev_ops vfe_v4l2_ops = { 1497 .core = &vfe_core_ops, 1498 .video = &vfe_video_ops, 1499 .pad = &vfe_pad_ops, 1500}; 1501 1502static const struct v4l2_subdev_internal_ops vfe_v4l2_internal_ops = { 1503 .open = vfe_init_formats, 1504}; 1505 1506static const struct media_entity_operations vfe_media_ops = { 1507 .link_setup = vfe_link_setup, 1508 .link_validate = v4l2_subdev_link_validate, 1509}; 1510 1511/* 1512 * msm_vfe_register_entities - Register subdev node for VFE module 1513 * @vfe: VFE device 1514 * @v4l2_dev: V4L2 device 1515 * 1516 * Initialize and register a subdev node for the VFE module. Then 1517 * call msm_video_register() to register the video device node which 1518 * will be connected to this subdev node. Then actually create the 1519 * media link between them. 1520 * 1521 * Return 0 on success or a negative error code otherwise 1522 */ 1523int msm_vfe_register_entities(struct vfe_device *vfe, 1524 struct v4l2_device *v4l2_dev) 1525{ 1526 struct device *dev = vfe->camss->dev; 1527 struct v4l2_subdev *sd; 1528 struct media_pad *pads; 1529 struct camss_video *video_out; 1530 int ret; 1531 int i; 1532 1533 for (i = 0; i < vfe->line_num; i++) { 1534 char name[32]; 1535 1536 sd = &vfe->line[i].subdev; 1537 pads = vfe->line[i].pads; 1538 video_out = &vfe->line[i].video_out; 1539 1540 v4l2_subdev_init(sd, &vfe_v4l2_ops); 1541 sd->internal_ops = &vfe_v4l2_internal_ops; 1542 sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; 1543 if (i == VFE_LINE_PIX) 1544 snprintf(sd->name, ARRAY_SIZE(sd->name), "%s%d_%s", 1545 MSM_VFE_NAME, vfe->id, "pix"); 1546 else 1547 snprintf(sd->name, ARRAY_SIZE(sd->name), "%s%d_%s%d", 1548 MSM_VFE_NAME, vfe->id, "rdi", i); 1549 1550 v4l2_set_subdevdata(sd, &vfe->line[i]); 1551 1552 ret = vfe_init_formats(sd, NULL); 1553 if (ret < 0) { 1554 dev_err(dev, "Failed to init format: %d\n", ret); 1555 goto error_init; 1556 } 1557 1558 pads[MSM_VFE_PAD_SINK].flags = MEDIA_PAD_FL_SINK; 1559 pads[MSM_VFE_PAD_SRC].flags = MEDIA_PAD_FL_SOURCE; 1560 1561 sd->entity.function = MEDIA_ENT_F_PROC_VIDEO_PIXEL_FORMATTER; 1562 sd->entity.ops = &vfe_media_ops; 1563 ret = media_entity_pads_init(&sd->entity, MSM_VFE_PADS_NUM, 1564 pads); 1565 if (ret < 0) { 1566 dev_err(dev, "Failed to init media entity: %d\n", ret); 1567 goto error_init; 1568 } 1569 1570 ret = v4l2_device_register_subdev(v4l2_dev, sd); 1571 if (ret < 0) { 1572 dev_err(dev, "Failed to register subdev: %d\n", ret); 1573 goto error_reg_subdev; 1574 } 1575 1576 video_out->ops = &vfe->video_ops; 1577 video_out->bpl_alignment = 8; 1578 video_out->line_based = 0; 1579 if (i == VFE_LINE_PIX) { 1580 video_out->bpl_alignment = 16; 1581 video_out->line_based = 1; 1582 } 1583 snprintf(name, ARRAY_SIZE(name), "%s%d_%s%d", 1584 MSM_VFE_NAME, vfe->id, "video", i); 1585 ret = msm_video_register(video_out, v4l2_dev, name, 1586 i == VFE_LINE_PIX ? 1 : 0); 1587 if (ret < 0) { 1588 dev_err(dev, "Failed to register video node: %d\n", 1589 ret); 1590 goto error_reg_video; 1591 } 1592 1593 ret = media_create_pad_link( 1594 &sd->entity, MSM_VFE_PAD_SRC, 1595 &video_out->vdev.entity, 0, 1596 MEDIA_LNK_FL_IMMUTABLE | MEDIA_LNK_FL_ENABLED); 1597 if (ret < 0) { 1598 dev_err(dev, "Failed to link %s->%s entities: %d\n", 1599 sd->entity.name, video_out->vdev.entity.name, 1600 ret); 1601 goto error_link; 1602 } 1603 } 1604 1605 return 0; 1606 1607error_link: 1608 msm_video_unregister(video_out); 1609 1610error_reg_video: 1611 v4l2_device_unregister_subdev(sd); 1612 1613error_reg_subdev: 1614 media_entity_cleanup(&sd->entity); 1615 1616error_init: 1617 for (i--; i >= 0; i--) { 1618 sd = &vfe->line[i].subdev; 1619 video_out = &vfe->line[i].video_out; 1620 1621 msm_video_unregister(video_out); 1622 v4l2_device_unregister_subdev(sd); 1623 media_entity_cleanup(&sd->entity); 1624 } 1625 1626 return ret; 1627} 1628 1629/* 1630 * msm_vfe_unregister_entities - Unregister VFE module subdev node 1631 * @vfe: VFE device 1632 */ 1633void msm_vfe_unregister_entities(struct vfe_device *vfe) 1634{ 1635 int i; 1636 1637 mutex_destroy(&vfe->power_lock); 1638 mutex_destroy(&vfe->stream_lock); 1639 1640 for (i = 0; i < vfe->line_num; i++) { 1641 struct v4l2_subdev *sd = &vfe->line[i].subdev; 1642 struct camss_video *video_out = &vfe->line[i].video_out; 1643 1644 msm_video_unregister(video_out); 1645 v4l2_device_unregister_subdev(sd); 1646 media_entity_cleanup(&sd->entity); 1647 } 1648}