773 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * Copyright (C) 2021-2023 Digiteq Automotive4 * author: Martin Tuma <martin.tuma@digiteqautomotive.com>5 *6 * This module handles all the sysfs info/configuration that is related to the7 * v4l2 input devices.8 */9 10#include <linux/device.h>11#include "mgb4_core.h"12#include "mgb4_i2c.h"13#include "mgb4_vin.h"14#include "mgb4_cmt.h"15#include "mgb4_sysfs.h"16 17/* Common for both FPDL3 and GMSL */18 19static ssize_t input_id_show(struct device *dev,20 struct device_attribute *attr, char *buf)21{22 struct video_device *vdev = to_video_device(dev);23 struct mgb4_vin_dev *vindev = video_get_drvdata(vdev);24 25 return sprintf(buf, "%d\n", vindev->config->id);26}27 28static ssize_t oldi_lane_width_show(struct device *dev,29 struct device_attribute *attr, char *buf)30{31 struct video_device *vdev = to_video_device(dev);32 struct mgb4_vin_dev *vindev = video_get_drvdata(vdev);33 struct mgb4_dev *mgbdev = vindev->mgbdev;34 u16 i2c_reg;35 u8 i2c_mask, i2c_single_val, i2c_dual_val;36 u32 config;37 int ret;38 39 i2c_reg = MGB4_IS_GMSL(mgbdev) ? 0x1CE : 0x49;40 i2c_mask = MGB4_IS_GMSL(mgbdev) ? 0x0E : 0x03;41 i2c_single_val = MGB4_IS_GMSL(mgbdev) ? 0x00 : 0x02;42 i2c_dual_val = MGB4_IS_GMSL(mgbdev) ? 0x0E : 0x00;43 44 mutex_lock(&mgbdev->i2c_lock);45 ret = mgb4_i2c_read_byte(&vindev->deser, i2c_reg);46 mutex_unlock(&mgbdev->i2c_lock);47 if (ret < 0)48 return -EIO;49 50 config = mgb4_read_reg(&mgbdev->video, vindev->config->regs.config);51 52 if (((config & (1U << 9)) && ((ret & i2c_mask) != i2c_dual_val)) ||53 (!(config & (1U << 9)) && ((ret & i2c_mask) != i2c_single_val))) {54 dev_err(dev, "I2C/FPGA register value mismatch\n");55 return -EINVAL;56 }57 58 return sprintf(buf, "%s\n", config & (1U << 9) ? "1" : "0");59}60 61/*62 * OLDI lane width change is expected to be called on live streams. Video device63 * locking/queue check is not needed.64 */65static ssize_t oldi_lane_width_store(struct device *dev,66 struct device_attribute *attr,67 const char *buf, size_t count)68{69 struct video_device *vdev = to_video_device(dev);70 struct mgb4_vin_dev *vindev = video_get_drvdata(vdev);71 struct mgb4_dev *mgbdev = vindev->mgbdev;72 u32 fpga_data;73 u16 i2c_reg;74 u8 i2c_mask, i2c_data;75 unsigned long val;76 int ret;77 78 ret = kstrtoul(buf, 10, &val);79 if (ret)80 return ret;81 82 switch (val) {83 case 0: /* single */84 fpga_data = 0;85 i2c_data = MGB4_IS_GMSL(mgbdev) ? 0x00 : 0x02;86 break;87 case 1: /* dual */88 fpga_data = 1U << 9;89 i2c_data = MGB4_IS_GMSL(mgbdev) ? 0x0E : 0x00;90 break;91 default:92 return -EINVAL;93 }94 95 i2c_reg = MGB4_IS_GMSL(mgbdev) ? 0x1CE : 0x49;96 i2c_mask = MGB4_IS_GMSL(mgbdev) ? 0x0E : 0x03;97 98 mutex_lock(&mgbdev->i2c_lock);99 ret = mgb4_i2c_mask_byte(&vindev->deser, i2c_reg, i2c_mask, i2c_data);100 mutex_unlock(&mgbdev->i2c_lock);101 if (ret < 0)102 return -EIO;103 mgb4_mask_reg(&mgbdev->video, vindev->config->regs.config, 1U << 9,104 fpga_data);105 if (MGB4_IS_GMSL(mgbdev)) {106 /* reset input link */107 mutex_lock(&mgbdev->i2c_lock);108 ret = mgb4_i2c_mask_byte(&vindev->deser, 0x10, 1U << 5, 1U << 5);109 mutex_unlock(&mgbdev->i2c_lock);110 if (ret < 0)111 return -EIO;112 }113 114 return count;115}116 117static ssize_t color_mapping_show(struct device *dev,118 struct device_attribute *attr, char *buf)119{120 struct video_device *vdev = to_video_device(dev);121 struct mgb4_vin_dev *vindev = video_get_drvdata(vdev);122 u32 config = mgb4_read_reg(&vindev->mgbdev->video,123 vindev->config->regs.config);124 125 return sprintf(buf, "%s\n", config & (1U << 8) ? "0" : "1");126}127 128/*129 * Color mapping change is expected to be called on live streams. Video device130 * locking/queue check is not needed.131 */132static ssize_t color_mapping_store(struct device *dev,133 struct device_attribute *attr,134 const char *buf, size_t count)135{136 struct video_device *vdev = to_video_device(dev);137 struct mgb4_vin_dev *vindev = video_get_drvdata(vdev);138 u32 fpga_data;139 unsigned long val;140 int ret;141 142 ret = kstrtoul(buf, 10, &val);143 if (ret)144 return ret;145 146 switch (val) {147 case 0: /* OLDI/JEIDA */148 fpga_data = (1U << 8);149 break;150 case 1: /* SPWG/VESA */151 fpga_data = 0;152 break;153 default:154 return -EINVAL;155 }156 157 mgb4_mask_reg(&vindev->mgbdev->video, vindev->config->regs.config,158 1U << 8, fpga_data);159 160 return count;161}162 163static ssize_t link_status_show(struct device *dev,164 struct device_attribute *attr, char *buf)165{166 struct video_device *vdev = to_video_device(dev);167 struct mgb4_vin_dev *vindev = video_get_drvdata(vdev);168 u32 status = mgb4_read_reg(&vindev->mgbdev->video,169 vindev->config->regs.status);170 171 return sprintf(buf, "%s\n", status & (1U << 2) ? "1" : "0");172}173 174static ssize_t stream_status_show(struct device *dev,175 struct device_attribute *attr, char *buf)176{177 struct video_device *vdev = to_video_device(dev);178 struct mgb4_vin_dev *vindev = video_get_drvdata(vdev);179 u32 status = mgb4_read_reg(&vindev->mgbdev->video,180 vindev->config->regs.status);181 182 return sprintf(buf, "%s\n", ((status & (1 << 14)) &&183 (status & (1 << 2)) && (status & (3 << 9))) ? "1" : "0");184}185 186static ssize_t video_width_show(struct device *dev,187 struct device_attribute *attr, char *buf)188{189 struct video_device *vdev = to_video_device(dev);190 struct mgb4_vin_dev *vindev = video_get_drvdata(vdev);191 u32 config = mgb4_read_reg(&vindev->mgbdev->video,192 vindev->config->regs.resolution);193 194 return sprintf(buf, "%u\n", config >> 16);195}196 197static ssize_t video_height_show(struct device *dev,198 struct device_attribute *attr, char *buf)199{200 struct video_device *vdev = to_video_device(dev);201 struct mgb4_vin_dev *vindev = video_get_drvdata(vdev);202 u32 config = mgb4_read_reg(&vindev->mgbdev->video,203 vindev->config->regs.resolution);204 205 return sprintf(buf, "%u\n", config & 0xFFFF);206}207 208static ssize_t hsync_status_show(struct device *dev,209 struct device_attribute *attr, char *buf)210{211 struct video_device *vdev = to_video_device(dev);212 struct mgb4_vin_dev *vindev = video_get_drvdata(vdev);213 u32 status = mgb4_read_reg(&vindev->mgbdev->video,214 vindev->config->regs.status);215 u32 res;216 217 if (!(status & (1U << 11)))218 res = 0x02; // not available219 else if (status & (1U << 12))220 res = 0x01; // active high221 else222 res = 0x00; // active low223 224 return sprintf(buf, "%u\n", res);225}226 227static ssize_t vsync_status_show(struct device *dev,228 struct device_attribute *attr, char *buf)229{230 struct video_device *vdev = to_video_device(dev);231 struct mgb4_vin_dev *vindev = video_get_drvdata(vdev);232 u32 status = mgb4_read_reg(&vindev->mgbdev->video,233 vindev->config->regs.status);234 u32 res;235 236 if (!(status & (1U << 11)))237 res = 0x02; // not available238 else if (status & (1U << 13))239 res = 0x01; // active high240 else241 res = 0x00; // active low242 243 return sprintf(buf, "%u\n", res);244}245 246static ssize_t hsync_gap_length_show(struct device *dev,247 struct device_attribute *attr,248 char *buf)249{250 struct video_device *vdev = to_video_device(dev);251 struct mgb4_vin_dev *vindev = video_get_drvdata(vdev);252 u32 sync = mgb4_read_reg(&vindev->mgbdev->video,253 vindev->config->regs.sync);254 255 return sprintf(buf, "%u\n", sync >> 16);256}257 258/*259 * HSYNC gap length change is expected to be called on live streams. Video260 * device locking/queue check is not needed.261 */262static ssize_t hsync_gap_length_store(struct device *dev,263 struct device_attribute *attr,264 const char *buf, size_t count)265{266 struct video_device *vdev = to_video_device(dev);267 struct mgb4_vin_dev *vindev = video_get_drvdata(vdev);268 unsigned long val;269 int ret;270 271 ret = kstrtoul(buf, 10, &val);272 if (ret)273 return ret;274 if (val > 0xFFFF)275 return -EINVAL;276 277 mgb4_mask_reg(&vindev->mgbdev->video, vindev->config->regs.sync,278 0xFFFF0000, val << 16);279 280 return count;281}282 283static ssize_t vsync_gap_length_show(struct device *dev,284 struct device_attribute *attr, char *buf)285{286 struct video_device *vdev = to_video_device(dev);287 struct mgb4_vin_dev *vindev = video_get_drvdata(vdev);288 u32 sync = mgb4_read_reg(&vindev->mgbdev->video,289 vindev->config->regs.sync);290 291 return sprintf(buf, "%u\n", sync & 0xFFFF);292}293 294/*295 * VSYNC gap length change is expected to be called on live streams. Video296 * device locking/queue check is not needed.297 */298static ssize_t vsync_gap_length_store(struct device *dev,299 struct device_attribute *attr,300 const char *buf, size_t count)301{302 struct video_device *vdev = to_video_device(dev);303 struct mgb4_vin_dev *vindev = video_get_drvdata(vdev);304 unsigned long val;305 int ret;306 307 ret = kstrtoul(buf, 10, &val);308 if (ret)309 return ret;310 if (val > 0xFFFF)311 return -EINVAL;312 313 mgb4_mask_reg(&vindev->mgbdev->video, vindev->config->regs.sync, 0xFFFF,314 val);315 316 return count;317}318 319static ssize_t pclk_frequency_show(struct device *dev,320 struct device_attribute *attr, char *buf)321{322 struct video_device *vdev = to_video_device(dev);323 struct mgb4_vin_dev *vindev = video_get_drvdata(vdev);324 u32 freq = mgb4_read_reg(&vindev->mgbdev->video,325 vindev->config->regs.pclk);326 327 return sprintf(buf, "%u\n", freq);328}329 330static ssize_t hsync_width_show(struct device *dev,331 struct device_attribute *attr, char *buf)332{333 struct video_device *vdev = to_video_device(dev);334 struct mgb4_vin_dev *vindev = video_get_drvdata(vdev);335 u32 sig = mgb4_read_reg(&vindev->mgbdev->video,336 vindev->config->regs.signal);337 338 return sprintf(buf, "%u\n", (sig & 0x00FF0000) >> 16);339}340 341static ssize_t vsync_width_show(struct device *dev,342 struct device_attribute *attr, char *buf)343{344 struct video_device *vdev = to_video_device(dev);345 struct mgb4_vin_dev *vindev = video_get_drvdata(vdev);346 u32 sig = mgb4_read_reg(&vindev->mgbdev->video,347 vindev->config->regs.signal2);348 349 return sprintf(buf, "%u\n", (sig & 0x00FF0000) >> 16);350}351 352static ssize_t hback_porch_show(struct device *dev,353 struct device_attribute *attr, char *buf)354{355 struct video_device *vdev = to_video_device(dev);356 struct mgb4_vin_dev *vindev = video_get_drvdata(vdev);357 u32 sig = mgb4_read_reg(&vindev->mgbdev->video,358 vindev->config->regs.signal);359 360 return sprintf(buf, "%u\n", (sig & 0x0000FF00) >> 8);361}362 363static ssize_t hfront_porch_show(struct device *dev,364 struct device_attribute *attr, char *buf)365{366 struct video_device *vdev = to_video_device(dev);367 struct mgb4_vin_dev *vindev = video_get_drvdata(vdev);368 u32 sig = mgb4_read_reg(&vindev->mgbdev->video,369 vindev->config->regs.signal);370 371 return sprintf(buf, "%u\n", (sig & 0x000000FF));372}373 374static ssize_t vback_porch_show(struct device *dev,375 struct device_attribute *attr, char *buf)376{377 struct video_device *vdev = to_video_device(dev);378 struct mgb4_vin_dev *vindev = video_get_drvdata(vdev);379 u32 sig = mgb4_read_reg(&vindev->mgbdev->video,380 vindev->config->regs.signal2);381 382 return sprintf(buf, "%u\n", (sig & 0x0000FF00) >> 8);383}384 385static ssize_t vfront_porch_show(struct device *dev,386 struct device_attribute *attr, char *buf)387{388 struct video_device *vdev = to_video_device(dev);389 struct mgb4_vin_dev *vindev = video_get_drvdata(vdev);390 u32 sig = mgb4_read_reg(&vindev->mgbdev->video,391 vindev->config->regs.signal2);392 393 return sprintf(buf, "%u\n", (sig & 0x000000FF));394}395 396static ssize_t frequency_range_show(struct device *dev,397 struct device_attribute *attr, char *buf)398{399 struct video_device *vdev = to_video_device(dev);400 struct mgb4_vin_dev *vindev = video_get_drvdata(vdev);401 402 return sprintf(buf, "%d\n", vindev->freq_range);403}404 405static ssize_t frequency_range_store(struct device *dev,406 struct device_attribute *attr,407 const char *buf, size_t count)408{409 struct video_device *vdev = to_video_device(dev);410 struct mgb4_vin_dev *vindev = video_get_drvdata(vdev);411 unsigned long val;412 int ret;413 414 ret = kstrtoul(buf, 10, &val);415 if (ret)416 return ret;417 if (val > 1)418 return -EINVAL;419 420 mutex_lock(vindev->vdev.lock);421 if (vb2_is_busy(vindev->vdev.queue)) {422 mutex_unlock(vindev->vdev.lock);423 return -EBUSY;424 }425 426 mgb4_cmt_set_vin_freq_range(vindev, val);427 vindev->freq_range = val;428 429 mutex_unlock(vindev->vdev.lock);430 431 return count;432}433 434/* FPDL3 only */435 436static ssize_t fpdl3_input_width_show(struct device *dev,437 struct device_attribute *attr, char *buf)438{439 struct video_device *vdev = to_video_device(dev);440 struct mgb4_vin_dev *vindev = video_get_drvdata(vdev);441 s32 ret;442 443 mutex_lock(&vindev->mgbdev->i2c_lock);444 ret = mgb4_i2c_read_byte(&vindev->deser, 0x34);445 mutex_unlock(&vindev->mgbdev->i2c_lock);446 if (ret < 0)447 return -EIO;448 449 switch ((u8)ret & 0x18) {450 case 0:451 return sprintf(buf, "0\n");452 case 0x10:453 return sprintf(buf, "1\n");454 case 0x08:455 return sprintf(buf, "2\n");456 default:457 return -EINVAL;458 }459}460 461/*462 * FPD-Link width change is expected to be called on live streams. Video device463 * locking/queue check is not needed.464 */465static ssize_t fpdl3_input_width_store(struct device *dev,466 struct device_attribute *attr,467 const char *buf, size_t count)468{469 struct video_device *vdev = to_video_device(dev);470 struct mgb4_vin_dev *vindev = video_get_drvdata(vdev);471 u8 i2c_data;472 unsigned long val;473 int ret;474 475 ret = kstrtoul(buf, 10, &val);476 if (ret)477 return ret;478 479 switch (val) {480 case 0: /* auto */481 i2c_data = 0x00;482 break;483 case 1: /* single */484 i2c_data = 0x10;485 break;486 case 2: /* dual */487 i2c_data = 0x08;488 break;489 default:490 return -EINVAL;491 }492 493 mutex_lock(&vindev->mgbdev->i2c_lock);494 ret = mgb4_i2c_mask_byte(&vindev->deser, 0x34, 0x18, i2c_data);495 mutex_unlock(&vindev->mgbdev->i2c_lock);496 if (ret < 0)497 return -EIO;498 499 return count;500}501 502/* GMSL only */503 504static ssize_t gmsl_mode_show(struct device *dev,505 struct device_attribute *attr, char *buf)506{507 struct video_device *vdev = to_video_device(dev);508 struct mgb4_vin_dev *vindev = video_get_drvdata(vdev);509 s32 r1, r300, r3;510 511 mutex_lock(&vindev->mgbdev->i2c_lock);512 r1 = mgb4_i2c_read_byte(&vindev->deser, 0x01);513 r300 = mgb4_i2c_read_byte(&vindev->deser, 0x300);514 r3 = mgb4_i2c_read_byte(&vindev->deser, 0x03);515 mutex_unlock(&vindev->mgbdev->i2c_lock);516 if (r1 < 0 || r300 < 0 || r3 < 0)517 return -EIO;518 519 if ((r1 & 0x03) == 0x03 && (r300 & 0x0C) == 0x0C && (r3 & 0xC0) == 0xC0)520 return sprintf(buf, "0\n");521 else if ((r1 & 0x03) == 0x02 && (r300 & 0x0C) == 0x08 && (r3 & 0xC0) == 0x00)522 return sprintf(buf, "1\n");523 else if ((r1 & 0x03) == 0x01 && (r300 & 0x0C) == 0x04 && (r3 & 0xC0) == 0x00)524 return sprintf(buf, "2\n");525 else if ((r1 & 0x03) == 0x00 && (r300 & 0x0C) == 0x00 && (r3 & 0xC0) == 0x00)526 return sprintf(buf, "3\n");527 else528 return -EINVAL;529}530 531/*532 * GMSL mode change is expected to be called on live streams. Video device533 * locking/queue check is not needed.534 */535static ssize_t gmsl_mode_store(struct device *dev,536 struct device_attribute *attr, const char *buf,537 size_t count)538{539 static const struct mgb4_i2c_kv G12[] = {540 {0x01, 0x03, 0x03}, {0x300, 0x0C, 0x0C}, {0x03, 0xC0, 0xC0}};541 static const struct mgb4_i2c_kv G6[] = {542 {0x01, 0x03, 0x02}, {0x300, 0x0C, 0x08}, {0x03, 0xC0, 0x00}};543 static const struct mgb4_i2c_kv G3[] = {544 {0x01, 0x03, 0x01}, {0x300, 0x0C, 0x04}, {0x03, 0xC0, 0x00}};545 static const struct mgb4_i2c_kv G1[] = {546 {0x01, 0x03, 0x00}, {0x300, 0x0C, 0x00}, {0x03, 0xC0, 0x00}};547 static const struct mgb4_i2c_kv reset[] = {548 {0x10, 1U << 5, 1U << 5}, {0x300, 1U << 6, 1U << 6}};549 struct video_device *vdev = to_video_device(dev);550 struct mgb4_vin_dev *vindev = video_get_drvdata(vdev);551 const struct mgb4_i2c_kv *values;552 unsigned long val;553 int ret;554 555 ret = kstrtoul(buf, 10, &val);556 if (ret)557 return ret;558 559 switch (val) {560 case 0: /* 12Gb/s */561 values = G12;562 break;563 case 1: /* 6Gb/s */564 values = G6;565 break;566 case 2: /* 3Gb/s */567 values = G3;568 break;569 case 3: /* 1.5Gb/s */570 values = G1;571 break;572 default:573 return -EINVAL;574 }575 576 mutex_lock(&vindev->mgbdev->i2c_lock);577 ret = mgb4_i2c_configure(&vindev->deser, values, 3);578 ret |= mgb4_i2c_configure(&vindev->deser, reset, 2);579 mutex_unlock(&vindev->mgbdev->i2c_lock);580 if (ret < 0)581 return -EIO;582 583 return count;584}585 586static ssize_t gmsl_stream_id_show(struct device *dev,587 struct device_attribute *attr, char *buf)588{589 struct video_device *vdev = to_video_device(dev);590 struct mgb4_vin_dev *vindev = video_get_drvdata(vdev);591 s32 ret;592 593 mutex_lock(&vindev->mgbdev->i2c_lock);594 ret = mgb4_i2c_read_byte(&vindev->deser, 0xA0);595 mutex_unlock(&vindev->mgbdev->i2c_lock);596 if (ret < 0)597 return -EIO;598 599 return sprintf(buf, "%d\n", ret & 0x03);600}601 602static ssize_t gmsl_stream_id_store(struct device *dev,603 struct device_attribute *attr,604 const char *buf, size_t count)605{606 struct video_device *vdev = to_video_device(dev);607 struct mgb4_vin_dev *vindev = video_get_drvdata(vdev);608 unsigned long val;609 int ret;610 611 ret = kstrtoul(buf, 10, &val);612 if (ret)613 return ret;614 if (val > 3)615 return -EINVAL;616 617 mutex_lock(vindev->vdev.lock);618 if (vb2_is_busy(vindev->vdev.queue)) {619 mutex_unlock(vindev->vdev.lock);620 return -EBUSY;621 }622 623 mutex_lock(&vindev->mgbdev->i2c_lock);624 ret = mgb4_i2c_mask_byte(&vindev->deser, 0xA0, 0x03, (u8)val);625 mutex_unlock(&vindev->mgbdev->i2c_lock);626 627 mutex_unlock(vindev->vdev.lock);628 629 return (ret < 0) ? -EIO : count;630}631 632static ssize_t gmsl_fec_show(struct device *dev, struct device_attribute *attr,633 char *buf)634{635 struct video_device *vdev = to_video_device(dev);636 struct mgb4_vin_dev *vindev = video_get_drvdata(vdev);637 s32 r3e0, r308;638 639 mutex_lock(&vindev->mgbdev->i2c_lock);640 r3e0 = mgb4_i2c_read_byte(&vindev->deser, 0x3E0);641 r308 = mgb4_i2c_read_byte(&vindev->deser, 0x308);642 mutex_unlock(&vindev->mgbdev->i2c_lock);643 if (r3e0 < 0 || r308 < 0)644 return -EIO;645 646 if ((r3e0 & 0x07) == 0x00 && (r308 & 0x01) == 0x00)647 return sprintf(buf, "0\n");648 else if ((r3e0 & 0x07) == 0x07 && (r308 & 0x01) == 0x01)649 return sprintf(buf, "1\n");650 else651 return -EINVAL;652}653 654/*655 * GMSL FEC change is expected to be called on live streams. Video device656 * locking/queue check is not needed.657 */658static ssize_t gmsl_fec_store(struct device *dev, struct device_attribute *attr,659 const char *buf, size_t count)660{661 struct video_device *vdev = to_video_device(dev);662 struct mgb4_vin_dev *vindev = video_get_drvdata(vdev);663 static const struct mgb4_i2c_kv enable[] = {664 {0x3E0, 0x07, 0x07}, {0x308, 0x01, 0x01}};665 static const struct mgb4_i2c_kv disable[] = {666 {0x3E0, 0x07, 0x00}, {0x308, 0x01, 0x00}};667 static const struct mgb4_i2c_kv reset[] = {668 {0x10, 1U << 5, 1U << 5}, {0x300, 1U << 6, 1U << 6}};669 const struct mgb4_i2c_kv *values;670 unsigned long val;671 int ret;672 673 ret = kstrtoul(buf, 10, &val);674 if (ret)675 return ret;676 677 switch (val) {678 case 0: /* disabled */679 values = disable;680 break;681 case 1: /* enabled */682 values = enable;683 break;684 default:685 return -EINVAL;686 }687 688 mutex_lock(&vindev->mgbdev->i2c_lock);689 ret = mgb4_i2c_configure(&vindev->deser, values, 2);690 ret |= mgb4_i2c_configure(&vindev->deser, reset, 2);691 mutex_unlock(&vindev->mgbdev->i2c_lock);692 if (ret < 0)693 return -EIO;694 695 return count;696}697 698static DEVICE_ATTR_RO(input_id);699static DEVICE_ATTR_RW(oldi_lane_width);700static DEVICE_ATTR_RW(color_mapping);701static DEVICE_ATTR_RO(link_status);702static DEVICE_ATTR_RO(stream_status);703static DEVICE_ATTR_RO(video_width);704static DEVICE_ATTR_RO(video_height);705static DEVICE_ATTR_RO(hsync_status);706static DEVICE_ATTR_RO(vsync_status);707static DEVICE_ATTR_RW(hsync_gap_length);708static DEVICE_ATTR_RW(vsync_gap_length);709static DEVICE_ATTR_RO(pclk_frequency);710static DEVICE_ATTR_RO(hsync_width);711static DEVICE_ATTR_RO(vsync_width);712static DEVICE_ATTR_RO(hback_porch);713static DEVICE_ATTR_RO(hfront_porch);714static DEVICE_ATTR_RO(vback_porch);715static DEVICE_ATTR_RO(vfront_porch);716static DEVICE_ATTR_RW(frequency_range);717 718static DEVICE_ATTR_RW(fpdl3_input_width);719 720static DEVICE_ATTR_RW(gmsl_mode);721static DEVICE_ATTR_RW(gmsl_stream_id);722static DEVICE_ATTR_RW(gmsl_fec);723 724struct attribute *mgb4_fpdl3_in_attrs[] = {725 &dev_attr_input_id.attr,726 &dev_attr_link_status.attr,727 &dev_attr_stream_status.attr,728 &dev_attr_video_width.attr,729 &dev_attr_video_height.attr,730 &dev_attr_hsync_status.attr,731 &dev_attr_vsync_status.attr,732 &dev_attr_oldi_lane_width.attr,733 &dev_attr_color_mapping.attr,734 &dev_attr_hsync_gap_length.attr,735 &dev_attr_vsync_gap_length.attr,736 &dev_attr_pclk_frequency.attr,737 &dev_attr_hsync_width.attr,738 &dev_attr_vsync_width.attr,739 &dev_attr_hback_porch.attr,740 &dev_attr_hfront_porch.attr,741 &dev_attr_vback_porch.attr,742 &dev_attr_vfront_porch.attr,743 &dev_attr_frequency_range.attr,744 &dev_attr_fpdl3_input_width.attr,745 NULL746};747 748struct attribute *mgb4_gmsl_in_attrs[] = {749 &dev_attr_input_id.attr,750 &dev_attr_link_status.attr,751 &dev_attr_stream_status.attr,752 &dev_attr_video_width.attr,753 &dev_attr_video_height.attr,754 &dev_attr_hsync_status.attr,755 &dev_attr_vsync_status.attr,756 &dev_attr_oldi_lane_width.attr,757 &dev_attr_color_mapping.attr,758 &dev_attr_hsync_gap_length.attr,759 &dev_attr_vsync_gap_length.attr,760 &dev_attr_pclk_frequency.attr,761 &dev_attr_hsync_width.attr,762 &dev_attr_vsync_width.attr,763 &dev_attr_hback_porch.attr,764 &dev_attr_hfront_porch.attr,765 &dev_attr_vback_porch.attr,766 &dev_attr_vfront_porch.attr,767 &dev_attr_frequency_range.attr,768 &dev_attr_gmsl_mode.attr,769 &dev_attr_gmsl_stream_id.attr,770 &dev_attr_gmsl_fec.attr,771 NULL772};773