1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * Copyright (C) 2021-2023 Digiteq Automotive 4 * author: Martin Tuma <martin.tuma@digiteqautomotive.com> 5 * 6 * This module handles all the sysfs info/configuration that is related to the 7 * v4l2 output devices. 8 */ 9 10 #include <linux/device.h> 11 #include <linux/nospec.h> 12 #include "mgb4_core.h" 13 #include "mgb4_i2c.h" 14 #include "mgb4_vout.h" 15 #include "mgb4_vin.h" 16 #include "mgb4_cmt.h" 17 #include "mgb4_sysfs.h" 18 19 static int loopin_cnt(struct mgb4_vin_dev *vindev) 20 { 21 struct mgb4_vout_dev *voutdev; 22 u32 config; 23 int i, cnt = 0; 24 25 for (i = 0; i < MGB4_VOUT_DEVICES; i++) { 26 voutdev = vindev->mgbdev->vout[i]; 27 if (!voutdev) 28 continue; 29 30 config = mgb4_read_reg(&voutdev->mgbdev->video, 31 voutdev->config->regs.config); 32 if ((config & 0xc) >> 2 == vindev->config->id) 33 cnt++; 34 } 35 36 return cnt; 37 } 38 39 static bool is_busy(struct video_device *dev) 40 { 41 bool ret; 42 43 mutex_lock(dev->lock); 44 ret = vb2_is_busy(dev->queue); 45 mutex_unlock(dev->lock); 46 47 return ret; 48 } 49 50 /* Common for both FPDL3 and GMSL */ 51 52 static ssize_t output_id_show(struct device *dev, 53 struct device_attribute *attr, char *buf) 54 { 55 struct video_device *vdev = to_video_device(dev); 56 struct mgb4_vout_dev *voutdev = video_get_drvdata(vdev); 57 58 return sprintf(buf, "%d\n", voutdev->config->id); 59 } 60 61 static ssize_t video_source_show(struct device *dev, 62 struct device_attribute *attr, char *buf) 63 { 64 struct video_device *vdev = to_video_device(dev); 65 struct mgb4_vout_dev *voutdev = video_get_drvdata(vdev); 66 u32 config = mgb4_read_reg(&voutdev->mgbdev->video, 67 voutdev->config->regs.config); 68 69 return sprintf(buf, "%u\n", (config & 0xc) >> 2); 70 } 71 72 /* 73 * Video source change may affect the buffer queue of ANY video input/output on 74 * the card thus if any of the inputs/outputs is in use, we do not allow 75 * the change. 76 * 77 * As we do not want to lock all the video devices at the same time, a two-stage 78 * locking strategy is used. In addition to the video device locking there is 79 * a global (PCI device) variable "io_reconfig" atomically checked/set when 80 * the reconfiguration is running. All the video devices check the variable in 81 * their queue_setup() functions and do not allow to start the queue when 82 * the reconfiguration has started. 83 */ 84 static ssize_t video_source_store(struct device *dev, 85 struct device_attribute *attr, 86 const char *buf, size_t count) 87 { 88 struct video_device *vdev = to_video_device(dev); 89 struct mgb4_vout_dev *voutdev = video_get_drvdata(vdev); 90 struct mgb4_dev *mgbdev = voutdev->mgbdev; 91 struct mgb4_vin_dev *loopin_new = NULL, *loopin_old = NULL; 92 unsigned long val; 93 ssize_t ret; 94 u32 config; 95 int i; 96 97 ret = kstrtoul(buf, 10, &val); 98 if (ret) 99 return ret; 100 if (val > 3) 101 return -EINVAL; 102 103 if (test_and_set_bit(0, &mgbdev->io_reconfig)) 104 return -EBUSY; 105 106 ret = -EBUSY; 107 for (i = 0; i < MGB4_VIN_DEVICES; i++) 108 if (mgbdev->vin[i] && is_busy(&mgbdev->vin[i]->vdev)) 109 goto end; 110 for (i = 0; i < MGB4_VOUT_DEVICES; i++) 111 if (mgbdev->vout[i] && is_busy(&mgbdev->vout[i]->vdev)) 112 goto end; 113 114 config = mgb4_read_reg(&mgbdev->video, voutdev->config->regs.config); 115 116 if (((config & 0xc) >> 2) < MGB4_VIN_DEVICES) 117 loopin_old = mgbdev->vin[(config & 0xc) >> 2]; 118 if (val < MGB4_VIN_DEVICES) { 119 val = array_index_nospec(val, MGB4_VIN_DEVICES); 120 loopin_new = mgbdev->vin[val]; 121 } 122 if (loopin_old && loopin_cnt(loopin_old) == 1) 123 mgb4_mask_reg(&mgbdev->video, loopin_old->config->regs.config, 124 0x2, 0x0); 125 if (loopin_new) 126 mgb4_mask_reg(&mgbdev->video, loopin_new->config->regs.config, 127 0x2, 0x2); 128 129 if (val == voutdev->config->id + MGB4_VIN_DEVICES) 130 mgb4_write_reg(&mgbdev->video, voutdev->config->regs.config, 131 config & ~(1 << 1)); 132 else 133 mgb4_write_reg(&mgbdev->video, voutdev->config->regs.config, 134 config | (1U << 1)); 135 136 mgb4_mask_reg(&mgbdev->video, voutdev->config->regs.config, 0xc, 137 val << 2); 138 139 ret = count; 140 end: 141 clear_bit(0, &mgbdev->io_reconfig); 142 143 return ret; 144 } 145 146 static ssize_t display_width_show(struct device *dev, 147 struct device_attribute *attr, char *buf) 148 { 149 struct video_device *vdev = to_video_device(dev); 150 struct mgb4_vout_dev *voutdev = video_get_drvdata(vdev); 151 u32 config = mgb4_read_reg(&voutdev->mgbdev->video, 152 voutdev->config->regs.resolution); 153 154 return sprintf(buf, "%u\n", config >> 16); 155 } 156 157 static ssize_t display_width_store(struct device *dev, 158 struct device_attribute *attr, 159 const char *buf, size_t count) 160 { 161 struct video_device *vdev = to_video_device(dev); 162 struct mgb4_vout_dev *voutdev = video_get_drvdata(vdev); 163 unsigned long val; 164 int ret; 165 166 ret = kstrtoul(buf, 10, &val); 167 if (ret) 168 return ret; 169 if (val > 0xFFFF) 170 return -EINVAL; 171 172 mutex_lock(voutdev->vdev.lock); 173 if (vb2_is_busy(voutdev->vdev.queue)) { 174 mutex_unlock(voutdev->vdev.lock); 175 return -EBUSY; 176 } 177 178 mgb4_mask_reg(&voutdev->mgbdev->video, voutdev->config->regs.resolution, 179 0xFFFF0000, val << 16); 180 181 mutex_unlock(voutdev->vdev.lock); 182 183 return count; 184 } 185 186 static ssize_t display_height_show(struct device *dev, 187 struct device_attribute *attr, char *buf) 188 { 189 struct video_device *vdev = to_video_device(dev); 190 struct mgb4_vout_dev *voutdev = video_get_drvdata(vdev); 191 u32 config = mgb4_read_reg(&voutdev->mgbdev->video, 192 voutdev->config->regs.resolution); 193 194 return sprintf(buf, "%u\n", config & 0xFFFF); 195 } 196 197 static ssize_t display_height_store(struct device *dev, 198 struct device_attribute *attr, 199 const char *buf, size_t count) 200 { 201 struct video_device *vdev = to_video_device(dev); 202 struct mgb4_vout_dev *voutdev = video_get_drvdata(vdev); 203 unsigned long val; 204 int ret; 205 206 ret = kstrtoul(buf, 10, &val); 207 if (ret) 208 return ret; 209 if (val > 0xFFFF) 210 return -EINVAL; 211 212 mutex_lock(voutdev->vdev.lock); 213 if (vb2_is_busy(voutdev->vdev.queue)) { 214 mutex_unlock(voutdev->vdev.lock); 215 return -EBUSY; 216 } 217 218 mgb4_mask_reg(&voutdev->mgbdev->video, voutdev->config->regs.resolution, 219 0xFFFF, val); 220 221 mutex_unlock(voutdev->vdev.lock); 222 223 return count; 224 } 225 226 static ssize_t frame_rate_show(struct device *dev, 227 struct device_attribute *attr, char *buf) 228 { 229 struct video_device *vdev = to_video_device(dev); 230 struct mgb4_vout_dev *voutdev = video_get_drvdata(vdev); 231 u32 period = mgb4_read_reg(&voutdev->mgbdev->video, 232 voutdev->config->regs.frame_limit); 233 234 return sprintf(buf, "%u\n", period ? MGB4_HW_FREQ / period : 0); 235 } 236 237 /* 238 * Frame rate change is expected to be called on live streams. Video device 239 * locking/queue check is not needed. 240 */ 241 static ssize_t frame_rate_store(struct device *dev, 242 struct device_attribute *attr, const char *buf, 243 size_t count) 244 { 245 struct video_device *vdev = to_video_device(dev); 246 struct mgb4_vout_dev *voutdev = video_get_drvdata(vdev); 247 unsigned long val; 248 int limit, ret; 249 250 ret = kstrtoul(buf, 10, &val); 251 if (ret) 252 return ret; 253 254 limit = val ? MGB4_HW_FREQ / val : 0; 255 mgb4_write_reg(&voutdev->mgbdev->video, 256 voutdev->config->regs.frame_limit, limit); 257 258 return count; 259 } 260 261 static ssize_t hsync_width_show(struct device *dev, 262 struct device_attribute *attr, char *buf) 263 { 264 struct video_device *vdev = to_video_device(dev); 265 struct mgb4_vout_dev *voutdev = video_get_drvdata(vdev); 266 u32 sig = mgb4_read_reg(&voutdev->mgbdev->video, 267 voutdev->config->regs.hsync); 268 269 return sprintf(buf, "%u\n", (sig & 0x00FF0000) >> 16); 270 } 271 272 /* 273 * HSYNC width change is expected to be called on live streams. Video device 274 * locking/queue check is not needed. 275 */ 276 static ssize_t hsync_width_store(struct device *dev, 277 struct device_attribute *attr, const char *buf, 278 size_t count) 279 { 280 struct video_device *vdev = to_video_device(dev); 281 struct mgb4_vout_dev *voutdev = video_get_drvdata(vdev); 282 unsigned long val; 283 int ret; 284 285 ret = kstrtoul(buf, 10, &val); 286 if (ret) 287 return ret; 288 if (val > 0xFF) 289 return -EINVAL; 290 291 mgb4_mask_reg(&voutdev->mgbdev->video, voutdev->config->regs.hsync, 292 0x00FF0000, val << 16); 293 294 return count; 295 } 296 297 static ssize_t vsync_width_show(struct device *dev, 298 struct device_attribute *attr, char *buf) 299 { 300 struct video_device *vdev = to_video_device(dev); 301 struct mgb4_vout_dev *voutdev = video_get_drvdata(vdev); 302 u32 sig = mgb4_read_reg(&voutdev->mgbdev->video, 303 voutdev->config->regs.vsync); 304 305 return sprintf(buf, "%u\n", (sig & 0x00FF0000) >> 16); 306 } 307 308 /* 309 * VSYNC vidth change is expected to be called on live streams. Video device 310 * locking/queue check is not needed. 311 */ 312 static ssize_t vsync_width_store(struct device *dev, 313 struct device_attribute *attr, const char *buf, 314 size_t count) 315 { 316 struct video_device *vdev = to_video_device(dev); 317 struct mgb4_vout_dev *voutdev = video_get_drvdata(vdev); 318 unsigned long val; 319 int ret; 320 321 ret = kstrtoul(buf, 10, &val); 322 if (ret) 323 return ret; 324 if (val > 0xFF) 325 return -EINVAL; 326 327 mgb4_mask_reg(&voutdev->mgbdev->video, voutdev->config->regs.vsync, 328 0x00FF0000, val << 16); 329 330 return count; 331 } 332 333 static ssize_t hback_porch_show(struct device *dev, 334 struct device_attribute *attr, char *buf) 335 { 336 struct video_device *vdev = to_video_device(dev); 337 struct mgb4_vout_dev *voutdev = video_get_drvdata(vdev); 338 u32 sig = mgb4_read_reg(&voutdev->mgbdev->video, 339 voutdev->config->regs.hsync); 340 341 return sprintf(buf, "%u\n", (sig & 0x0000FF00) >> 8); 342 } 343 344 /* 345 * hback porch change is expected to be called on live streams. Video device 346 * locking/queue check is not needed. 347 */ 348 static ssize_t hback_porch_store(struct device *dev, 349 struct device_attribute *attr, const char *buf, 350 size_t count) 351 { 352 struct video_device *vdev = to_video_device(dev); 353 struct mgb4_vout_dev *voutdev = video_get_drvdata(vdev); 354 unsigned long val; 355 int ret; 356 357 ret = kstrtoul(buf, 10, &val); 358 if (ret) 359 return ret; 360 if (val > 0xFF) 361 return -EINVAL; 362 363 mgb4_mask_reg(&voutdev->mgbdev->video, voutdev->config->regs.hsync, 364 0x0000FF00, val << 8); 365 366 return count; 367 } 368 369 static ssize_t vback_porch_show(struct device *dev, 370 struct device_attribute *attr, char *buf) 371 { 372 struct video_device *vdev = to_video_device(dev); 373 struct mgb4_vout_dev *voutdev = video_get_drvdata(vdev); 374 u32 sig = mgb4_read_reg(&voutdev->mgbdev->video, 375 voutdev->config->regs.vsync); 376 377 return sprintf(buf, "%u\n", (sig & 0x0000FF00) >> 8); 378 } 379 380 /* 381 * vback porch change is expected to be called on live streams. Video device 382 * locking/queue check is not needed. 383 */ 384 static ssize_t vback_porch_store(struct device *dev, 385 struct device_attribute *attr, const char *buf, 386 size_t count) 387 { 388 struct video_device *vdev = to_video_device(dev); 389 struct mgb4_vout_dev *voutdev = video_get_drvdata(vdev); 390 unsigned long val; 391 int ret; 392 393 ret = kstrtoul(buf, 10, &val); 394 if (ret) 395 return ret; 396 if (val > 0xFF) 397 return -EINVAL; 398 399 mgb4_mask_reg(&voutdev->mgbdev->video, voutdev->config->regs.vsync, 400 0x0000FF00, val << 8); 401 402 return count; 403 } 404 405 static ssize_t hfront_porch_show(struct device *dev, 406 struct device_attribute *attr, char *buf) 407 { 408 struct video_device *vdev = to_video_device(dev); 409 struct mgb4_vout_dev *voutdev = video_get_drvdata(vdev); 410 u32 sig = mgb4_read_reg(&voutdev->mgbdev->video, 411 voutdev->config->regs.hsync); 412 413 return sprintf(buf, "%u\n", (sig & 0x000000FF)); 414 } 415 416 /* 417 * hfront porch change is expected to be called on live streams. Video device 418 * locking/queue check is not needed. 419 */ 420 static ssize_t hfront_porch_store(struct device *dev, 421 struct device_attribute *attr, 422 const char *buf, size_t count) 423 { 424 struct video_device *vdev = to_video_device(dev); 425 struct mgb4_vout_dev *voutdev = video_get_drvdata(vdev); 426 unsigned long val; 427 int ret; 428 429 ret = kstrtoul(buf, 10, &val); 430 if (ret) 431 return ret; 432 if (val > 0xFF) 433 return -EINVAL; 434 435 mgb4_mask_reg(&voutdev->mgbdev->video, voutdev->config->regs.hsync, 436 0x000000FF, val); 437 438 return count; 439 } 440 441 static ssize_t vfront_porch_show(struct device *dev, 442 struct device_attribute *attr, char *buf) 443 { 444 struct video_device *vdev = to_video_device(dev); 445 struct mgb4_vout_dev *voutdev = video_get_drvdata(vdev); 446 u32 sig = mgb4_read_reg(&voutdev->mgbdev->video, 447 voutdev->config->regs.vsync); 448 449 return sprintf(buf, "%u\n", (sig & 0x000000FF)); 450 } 451 452 /* 453 * vfront porch change is expected to be called on live streams. Video device 454 * locking/queue check is not needed. 455 */ 456 static ssize_t vfront_porch_store(struct device *dev, 457 struct device_attribute *attr, const char *buf, 458 size_t count) 459 { 460 struct video_device *vdev = to_video_device(dev); 461 struct mgb4_vout_dev *voutdev = video_get_drvdata(vdev); 462 unsigned long val; 463 int ret; 464 465 ret = kstrtoul(buf, 10, &val); 466 if (ret) 467 return ret; 468 if (val > 0xFF) 469 return -EINVAL; 470 471 mgb4_mask_reg(&voutdev->mgbdev->video, voutdev->config->regs.vsync, 472 0x000000FF, val); 473 474 return count; 475 } 476 477 /* FPDL3 only */ 478 479 static ssize_t hsync_polarity_show(struct device *dev, 480 struct device_attribute *attr, char *buf) 481 { 482 struct video_device *vdev = to_video_device(dev); 483 struct mgb4_vout_dev *voutdev = video_get_drvdata(vdev); 484 u32 config = mgb4_read_reg(&voutdev->mgbdev->video, 485 voutdev->config->regs.hsync); 486 487 return sprintf(buf, "%u\n", (config & (1U << 31)) >> 31); 488 } 489 490 /* 491 * HSYNC polarity change is expected to be called on live streams. Video device 492 * locking/queue check is not needed. 493 */ 494 static ssize_t hsync_polarity_store(struct device *dev, 495 struct device_attribute *attr, 496 const char *buf, size_t count) 497 { 498 struct video_device *vdev = to_video_device(dev); 499 struct mgb4_vout_dev *voutdev = video_get_drvdata(vdev); 500 unsigned long val; 501 int ret; 502 503 ret = kstrtoul(buf, 10, &val); 504 if (ret) 505 return ret; 506 if (val > 1) 507 return -EINVAL; 508 509 mgb4_mask_reg(&voutdev->mgbdev->video, voutdev->config->regs.hsync, 510 (1U << 31), val << 31); 511 512 return count; 513 } 514 515 static ssize_t vsync_polarity_show(struct device *dev, 516 struct device_attribute *attr, char *buf) 517 { 518 struct video_device *vdev = to_video_device(dev); 519 struct mgb4_vout_dev *voutdev = video_get_drvdata(vdev); 520 u32 config = mgb4_read_reg(&voutdev->mgbdev->video, 521 voutdev->config->regs.vsync); 522 523 return sprintf(buf, "%u\n", (config & (1U << 31)) >> 31); 524 } 525 526 /* 527 * VSYNC polarity change is expected to be called on live streams. Video device 528 * locking/queue check is not needed. 529 */ 530 static ssize_t vsync_polarity_store(struct device *dev, 531 struct device_attribute *attr, 532 const char *buf, size_t count) 533 { 534 struct video_device *vdev = to_video_device(dev); 535 struct mgb4_vout_dev *voutdev = video_get_drvdata(vdev); 536 unsigned long val; 537 int ret; 538 539 ret = kstrtoul(buf, 10, &val); 540 if (ret) 541 return ret; 542 if (val > 1) 543 return -EINVAL; 544 545 mgb4_mask_reg(&voutdev->mgbdev->video, voutdev->config->regs.vsync, 546 (1U << 31), val << 31); 547 548 return count; 549 } 550 551 static ssize_t de_polarity_show(struct device *dev, 552 struct device_attribute *attr, char *buf) 553 { 554 struct video_device *vdev = to_video_device(dev); 555 struct mgb4_vout_dev *voutdev = video_get_drvdata(vdev); 556 u32 config = mgb4_read_reg(&voutdev->mgbdev->video, 557 voutdev->config->regs.vsync); 558 559 return sprintf(buf, "%u\n", (config & (1U << 30)) >> 30); 560 } 561 562 /* 563 * DE polarity change is expected to be called on live streams. Video device 564 * locking/queue check is not needed. 565 */ 566 static ssize_t de_polarity_store(struct device *dev, 567 struct device_attribute *attr, const char *buf, 568 size_t count) 569 { 570 struct video_device *vdev = to_video_device(dev); 571 struct mgb4_vout_dev *voutdev = video_get_drvdata(vdev); 572 unsigned long val; 573 int ret; 574 575 ret = kstrtoul(buf, 10, &val); 576 if (ret) 577 return ret; 578 if (val > 1) 579 return -EINVAL; 580 581 mgb4_mask_reg(&voutdev->mgbdev->video, voutdev->config->regs.vsync, 582 (1U << 30), val << 30); 583 584 return count; 585 } 586 587 static ssize_t fpdl3_output_width_show(struct device *dev, 588 struct device_attribute *attr, char *buf) 589 { 590 struct video_device *vdev = to_video_device(dev); 591 struct mgb4_vout_dev *voutdev = video_get_drvdata(vdev); 592 s32 ret; 593 594 mutex_lock(&voutdev->mgbdev->i2c_lock); 595 ret = mgb4_i2c_read_byte(&voutdev->ser, 0x5B); 596 mutex_unlock(&voutdev->mgbdev->i2c_lock); 597 if (ret < 0) 598 return -EIO; 599 600 switch ((u8)ret & 0x03) { 601 case 0: 602 return sprintf(buf, "0\n"); 603 case 1: 604 return sprintf(buf, "1\n"); 605 case 3: 606 return sprintf(buf, "2\n"); 607 default: 608 return -EINVAL; 609 } 610 } 611 612 /* 613 * FPD-Link width change is expected to be called on live streams. Video device 614 * locking/queue check is not needed. 615 */ 616 static ssize_t fpdl3_output_width_store(struct device *dev, 617 struct device_attribute *attr, 618 const char *buf, size_t count) 619 { 620 struct video_device *vdev = to_video_device(dev); 621 struct mgb4_vout_dev *voutdev = video_get_drvdata(vdev); 622 u8 i2c_data; 623 unsigned long val; 624 int ret; 625 626 ret = kstrtoul(buf, 10, &val); 627 if (ret) 628 return ret; 629 630 switch (val) { 631 case 0: /* auto */ 632 i2c_data = 0x00; 633 break; 634 case 1: /* single */ 635 i2c_data = 0x01; 636 break; 637 case 2: /* dual */ 638 i2c_data = 0x03; 639 break; 640 default: 641 return -EINVAL; 642 } 643 644 mutex_lock(&voutdev->mgbdev->i2c_lock); 645 ret = mgb4_i2c_mask_byte(&voutdev->ser, 0x5B, 0x03, i2c_data); 646 mutex_unlock(&voutdev->mgbdev->i2c_lock); 647 if (ret < 0) 648 return -EIO; 649 650 return count; 651 } 652 653 static ssize_t pclk_frequency_show(struct device *dev, 654 struct device_attribute *attr, char *buf) 655 { 656 struct video_device *vdev = to_video_device(dev); 657 struct mgb4_vout_dev *voutdev = video_get_drvdata(vdev); 658 659 return sprintf(buf, "%u\n", voutdev->freq); 660 } 661 662 static ssize_t pclk_frequency_store(struct device *dev, 663 struct device_attribute *attr, 664 const char *buf, size_t count) 665 { 666 struct video_device *vdev = to_video_device(dev); 667 struct mgb4_vout_dev *voutdev = video_get_drvdata(vdev); 668 unsigned long val; 669 int ret; 670 unsigned int dp; 671 672 ret = kstrtoul(buf, 10, &val); 673 if (ret) 674 return ret; 675 676 mutex_lock(voutdev->vdev.lock); 677 if (vb2_is_busy(voutdev->vdev.queue)) { 678 mutex_unlock(voutdev->vdev.lock); 679 return -EBUSY; 680 } 681 682 dp = (val > 50000) ? 1 : 0; 683 voutdev->freq = mgb4_cmt_set_vout_freq(voutdev, val >> dp) << dp; 684 685 mgb4_mask_reg(&voutdev->mgbdev->video, voutdev->config->regs.config, 686 0x10, dp << 4); 687 mutex_lock(&voutdev->mgbdev->i2c_lock); 688 ret = mgb4_i2c_mask_byte(&voutdev->ser, 0x4F, 1 << 6, ((~dp) & 1) << 6); 689 mutex_unlock(&voutdev->mgbdev->i2c_lock); 690 691 mutex_unlock(voutdev->vdev.lock); 692 693 return (ret < 0) ? -EIO : count; 694 } 695 696 static DEVICE_ATTR_RO(output_id); 697 static DEVICE_ATTR_RW(video_source); 698 static DEVICE_ATTR_RW(display_width); 699 static DEVICE_ATTR_RW(display_height); 700 static DEVICE_ATTR_RW(frame_rate); 701 static DEVICE_ATTR_RW(hsync_polarity); 702 static DEVICE_ATTR_RW(vsync_polarity); 703 static DEVICE_ATTR_RW(de_polarity); 704 static DEVICE_ATTR_RW(pclk_frequency); 705 static DEVICE_ATTR_RW(hsync_width); 706 static DEVICE_ATTR_RW(vsync_width); 707 static DEVICE_ATTR_RW(hback_porch); 708 static DEVICE_ATTR_RW(hfront_porch); 709 static DEVICE_ATTR_RW(vback_porch); 710 static DEVICE_ATTR_RW(vfront_porch); 711 712 static DEVICE_ATTR_RW(fpdl3_output_width); 713 714 struct attribute *mgb4_fpdl3_out_attrs[] = { 715 &dev_attr_output_id.attr, 716 &dev_attr_video_source.attr, 717 &dev_attr_display_width.attr, 718 &dev_attr_display_height.attr, 719 &dev_attr_frame_rate.attr, 720 &dev_attr_hsync_polarity.attr, 721 &dev_attr_vsync_polarity.attr, 722 &dev_attr_de_polarity.attr, 723 &dev_attr_pclk_frequency.attr, 724 &dev_attr_hsync_width.attr, 725 &dev_attr_vsync_width.attr, 726 &dev_attr_hback_porch.attr, 727 &dev_attr_hfront_porch.attr, 728 &dev_attr_vback_porch.attr, 729 &dev_attr_vfront_porch.attr, 730 &dev_attr_fpdl3_output_width.attr, 731 NULL 732 }; 733 734 struct attribute *mgb4_gmsl_out_attrs[] = { 735 &dev_attr_output_id.attr, 736 &dev_attr_video_source.attr, 737 &dev_attr_display_width.attr, 738 &dev_attr_display_height.attr, 739 &dev_attr_frame_rate.attr, 740 NULL 741 }; 742