File Index
Files and directories
Sign in
FILE

mgb4_sysfs_out.c

File preview with syntax highlighting.

linux-6.19.14/drivers/media/pci/mgb4/mgb4_sysfs_out.c C
  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
 19static 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
 39static 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
 52static 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
 61static 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 */
 84static 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;
140end:
141	clear_bit(0, &mgbdev->io_reconfig);
142
143	return ret;
144}
145
146static 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
157static 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
186static 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
197static 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
226static 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 */
241static 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
261static 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 */
276static 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
297static 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 */
312static 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
333static 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 */
348static 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
369static 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 */
384static 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
405static 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 */
420static 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
441static 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 */
456static 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
479static 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 */
494static 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
515static 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 */
530static 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
551static 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 */
566static 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
587static 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 */
616static 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
653static 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
662static 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
696static DEVICE_ATTR_RO(output_id);
697static DEVICE_ATTR_RW(video_source);
698static DEVICE_ATTR_RW(display_width);
699static DEVICE_ATTR_RW(display_height);
700static DEVICE_ATTR_RW(frame_rate);
701static DEVICE_ATTR_RW(hsync_polarity);
702static DEVICE_ATTR_RW(vsync_polarity);
703static DEVICE_ATTR_RW(de_polarity);
704static DEVICE_ATTR_RW(pclk_frequency);
705static DEVICE_ATTR_RW(hsync_width);
706static DEVICE_ATTR_RW(vsync_width);
707static DEVICE_ATTR_RW(hback_porch);
708static DEVICE_ATTR_RW(hfront_porch);
709static DEVICE_ATTR_RW(vback_porch);
710static DEVICE_ATTR_RW(vfront_porch);
711
712static DEVICE_ATTR_RW(fpdl3_output_width);
713
714struct 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
734struct 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};
~/ Read-only file preview.