xref: /linux/drivers/media/pci/mgb4/mgb4_sysfs_out.c (revision eb01fe7abbe2d0b38824d2a93fdb4cc3eaf2ccc1)
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_period);
233 
234 	return sprintf(buf, "%u\n", 125000000 / period);
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 ret;
249 
250 	ret = kstrtoul(buf, 10, &val);
251 	if (ret)
252 		return ret;
253 
254 	mgb4_write_reg(&voutdev->mgbdev->video,
255 		       voutdev->config->regs.frame_period, 125000000 / val);
256 
257 	return count;
258 }
259 
260 static ssize_t hsync_width_show(struct device *dev,
261 				struct device_attribute *attr, char *buf)
262 {
263 	struct video_device *vdev = to_video_device(dev);
264 	struct mgb4_vout_dev *voutdev = video_get_drvdata(vdev);
265 	u32 sig = mgb4_read_reg(&voutdev->mgbdev->video,
266 				voutdev->config->regs.hsync);
267 
268 	return sprintf(buf, "%u\n", (sig & 0x00FF0000) >> 16);
269 }
270 
271 /*
272  * HSYNC width change is expected to be called on live streams. Video device
273  * locking/queue check is not needed.
274  */
275 static ssize_t hsync_width_store(struct device *dev,
276 				 struct device_attribute *attr, const char *buf,
277 				 size_t count)
278 {
279 	struct video_device *vdev = to_video_device(dev);
280 	struct mgb4_vout_dev *voutdev = video_get_drvdata(vdev);
281 	unsigned long val;
282 	int ret;
283 
284 	ret = kstrtoul(buf, 10, &val);
285 	if (ret)
286 		return ret;
287 	if (val > 0xFF)
288 		return -EINVAL;
289 
290 	mgb4_mask_reg(&voutdev->mgbdev->video, voutdev->config->regs.hsync,
291 		      0x00FF0000, val << 16);
292 
293 	return count;
294 }
295 
296 static ssize_t vsync_width_show(struct device *dev,
297 				struct device_attribute *attr, char *buf)
298 {
299 	struct video_device *vdev = to_video_device(dev);
300 	struct mgb4_vout_dev *voutdev = video_get_drvdata(vdev);
301 	u32 sig = mgb4_read_reg(&voutdev->mgbdev->video,
302 				voutdev->config->regs.vsync);
303 
304 	return sprintf(buf, "%u\n", (sig & 0x00FF0000) >> 16);
305 }
306 
307 /*
308  * VSYNC vidth change is expected to be called on live streams. Video device
309  * locking/queue check is not needed.
310  */
311 static ssize_t vsync_width_store(struct device *dev,
312 				 struct device_attribute *attr, const char *buf,
313 				 size_t count)
314 {
315 	struct video_device *vdev = to_video_device(dev);
316 	struct mgb4_vout_dev *voutdev = video_get_drvdata(vdev);
317 	unsigned long val;
318 	int ret;
319 
320 	ret = kstrtoul(buf, 10, &val);
321 	if (ret)
322 		return ret;
323 	if (val > 0xFF)
324 		return -EINVAL;
325 
326 	mgb4_mask_reg(&voutdev->mgbdev->video, voutdev->config->regs.vsync,
327 		      0x00FF0000, val << 16);
328 
329 	return count;
330 }
331 
332 static ssize_t hback_porch_show(struct device *dev,
333 				struct device_attribute *attr, char *buf)
334 {
335 	struct video_device *vdev = to_video_device(dev);
336 	struct mgb4_vout_dev *voutdev = video_get_drvdata(vdev);
337 	u32 sig = mgb4_read_reg(&voutdev->mgbdev->video,
338 				voutdev->config->regs.hsync);
339 
340 	return sprintf(buf, "%u\n", (sig & 0x0000FF00) >> 8);
341 }
342 
343 /*
344  * hback porch change is expected to be called on live streams. Video device
345  * locking/queue check is not needed.
346  */
347 static ssize_t hback_porch_store(struct device *dev,
348 				 struct device_attribute *attr, const char *buf,
349 				 size_t count)
350 {
351 	struct video_device *vdev = to_video_device(dev);
352 	struct mgb4_vout_dev *voutdev = video_get_drvdata(vdev);
353 	unsigned long val;
354 	int ret;
355 
356 	ret = kstrtoul(buf, 10, &val);
357 	if (ret)
358 		return ret;
359 	if (val > 0xFF)
360 		return -EINVAL;
361 
362 	mgb4_mask_reg(&voutdev->mgbdev->video, voutdev->config->regs.hsync,
363 		      0x0000FF00, val << 8);
364 
365 	return count;
366 }
367 
368 static ssize_t vback_porch_show(struct device *dev,
369 				struct device_attribute *attr, char *buf)
370 {
371 	struct video_device *vdev = to_video_device(dev);
372 	struct mgb4_vout_dev *voutdev = video_get_drvdata(vdev);
373 	u32 sig = mgb4_read_reg(&voutdev->mgbdev->video,
374 				voutdev->config->regs.vsync);
375 
376 	return sprintf(buf, "%u\n", (sig & 0x0000FF00) >> 8);
377 }
378 
379 /*
380  * vback porch change is expected to be called on live streams. Video device
381  * locking/queue check is not needed.
382  */
383 static ssize_t vback_porch_store(struct device *dev,
384 				 struct device_attribute *attr, const char *buf,
385 				 size_t count)
386 {
387 	struct video_device *vdev = to_video_device(dev);
388 	struct mgb4_vout_dev *voutdev = video_get_drvdata(vdev);
389 	unsigned long val;
390 	int ret;
391 
392 	ret = kstrtoul(buf, 10, &val);
393 	if (ret)
394 		return ret;
395 	if (val > 0xFF)
396 		return -EINVAL;
397 
398 	mgb4_mask_reg(&voutdev->mgbdev->video, voutdev->config->regs.vsync,
399 		      0x0000FF00, val << 8);
400 
401 	return count;
402 }
403 
404 static ssize_t hfront_porch_show(struct device *dev,
405 				 struct device_attribute *attr, char *buf)
406 {
407 	struct video_device *vdev = to_video_device(dev);
408 	struct mgb4_vout_dev *voutdev = video_get_drvdata(vdev);
409 	u32 sig = mgb4_read_reg(&voutdev->mgbdev->video,
410 				voutdev->config->regs.hsync);
411 
412 	return sprintf(buf, "%u\n", (sig & 0x000000FF));
413 }
414 
415 /*
416  * hfront porch change is expected to be called on live streams. Video device
417  * locking/queue check is not needed.
418  */
419 static ssize_t hfront_porch_store(struct device *dev,
420 				  struct device_attribute *attr,
421 				  const char *buf, size_t count)
422 {
423 	struct video_device *vdev = to_video_device(dev);
424 	struct mgb4_vout_dev *voutdev = video_get_drvdata(vdev);
425 	unsigned long val;
426 	int ret;
427 
428 	ret = kstrtoul(buf, 10, &val);
429 	if (ret)
430 		return ret;
431 	if (val > 0xFF)
432 		return -EINVAL;
433 
434 	mgb4_mask_reg(&voutdev->mgbdev->video, voutdev->config->regs.hsync,
435 		      0x000000FF, val);
436 
437 	return count;
438 }
439 
440 static ssize_t vfront_porch_show(struct device *dev,
441 				 struct device_attribute *attr, char *buf)
442 {
443 	struct video_device *vdev = to_video_device(dev);
444 	struct mgb4_vout_dev *voutdev = video_get_drvdata(vdev);
445 	u32 sig = mgb4_read_reg(&voutdev->mgbdev->video,
446 				voutdev->config->regs.vsync);
447 
448 	return sprintf(buf, "%u\n", (sig & 0x000000FF));
449 }
450 
451 /*
452  * vfront porch change is expected to be called on live streams. Video device
453  * locking/queue check is not needed.
454  */
455 static ssize_t vfront_porch_store(struct device *dev,
456 				  struct device_attribute *attr, const char *buf,
457 				  size_t count)
458 {
459 	struct video_device *vdev = to_video_device(dev);
460 	struct mgb4_vout_dev *voutdev = video_get_drvdata(vdev);
461 	unsigned long val;
462 	int ret;
463 
464 	ret = kstrtoul(buf, 10, &val);
465 	if (ret)
466 		return ret;
467 	if (val > 0xFF)
468 		return -EINVAL;
469 
470 	mgb4_mask_reg(&voutdev->mgbdev->video, voutdev->config->regs.vsync,
471 		      0x000000FF, val);
472 
473 	return count;
474 }
475 
476 /* FPDL3 only */
477 
478 static ssize_t hsync_polarity_show(struct device *dev,
479 				   struct device_attribute *attr, char *buf)
480 {
481 	struct video_device *vdev = to_video_device(dev);
482 	struct mgb4_vout_dev *voutdev = video_get_drvdata(vdev);
483 	u32 config = mgb4_read_reg(&voutdev->mgbdev->video,
484 	  voutdev->config->regs.hsync);
485 
486 	return sprintf(buf, "%u\n", (config & (1U << 31)) >> 31);
487 }
488 
489 /*
490  * HSYNC polarity change is expected to be called on live streams. Video device
491  * locking/queue check is not needed.
492  */
493 static ssize_t hsync_polarity_store(struct device *dev,
494 				    struct device_attribute *attr,
495 				    const char *buf, size_t count)
496 {
497 	struct video_device *vdev = to_video_device(dev);
498 	struct mgb4_vout_dev *voutdev = video_get_drvdata(vdev);
499 	unsigned long val;
500 	int ret;
501 
502 	ret = kstrtoul(buf, 10, &val);
503 	if (ret)
504 		return ret;
505 	if (val > 1)
506 		return -EINVAL;
507 
508 	mgb4_mask_reg(&voutdev->mgbdev->video, voutdev->config->regs.hsync,
509 		      (1U << 31), val << 31);
510 
511 	return count;
512 }
513 
514 static ssize_t vsync_polarity_show(struct device *dev,
515 				   struct device_attribute *attr, char *buf)
516 {
517 	struct video_device *vdev = to_video_device(dev);
518 	struct mgb4_vout_dev *voutdev = video_get_drvdata(vdev);
519 	u32 config = mgb4_read_reg(&voutdev->mgbdev->video,
520 	  voutdev->config->regs.vsync);
521 
522 	return sprintf(buf, "%u\n", (config & (1U << 31)) >> 31);
523 }
524 
525 /*
526  * VSYNC polarity change is expected to be called on live streams. Video device
527  * locking/queue check is not needed.
528  */
529 static ssize_t vsync_polarity_store(struct device *dev,
530 				    struct device_attribute *attr,
531 				    const char *buf, size_t count)
532 {
533 	struct video_device *vdev = to_video_device(dev);
534 	struct mgb4_vout_dev *voutdev = video_get_drvdata(vdev);
535 	unsigned long val;
536 	int ret;
537 
538 	ret = kstrtoul(buf, 10, &val);
539 	if (ret)
540 		return ret;
541 	if (val > 1)
542 		return -EINVAL;
543 
544 	mgb4_mask_reg(&voutdev->mgbdev->video, voutdev->config->regs.vsync,
545 		      (1U << 31), val << 31);
546 
547 	return count;
548 }
549 
550 static ssize_t de_polarity_show(struct device *dev,
551 				struct device_attribute *attr, char *buf)
552 {
553 	struct video_device *vdev = to_video_device(dev);
554 	struct mgb4_vout_dev *voutdev = video_get_drvdata(vdev);
555 	u32 config = mgb4_read_reg(&voutdev->mgbdev->video,
556 	  voutdev->config->regs.vsync);
557 
558 	return sprintf(buf, "%u\n", (config & (1U << 30)) >> 30);
559 }
560 
561 /*
562  * DE polarity change is expected to be called on live streams. Video device
563  * locking/queue check is not needed.
564  */
565 static ssize_t de_polarity_store(struct device *dev,
566 				 struct device_attribute *attr, const char *buf,
567 				 size_t count)
568 {
569 	struct video_device *vdev = to_video_device(dev);
570 	struct mgb4_vout_dev *voutdev = video_get_drvdata(vdev);
571 	unsigned long val;
572 	int ret;
573 
574 	ret = kstrtoul(buf, 10, &val);
575 	if (ret)
576 		return ret;
577 	if (val > 1)
578 		return -EINVAL;
579 
580 	mgb4_mask_reg(&voutdev->mgbdev->video, voutdev->config->regs.vsync,
581 		      (1U << 30), val << 30);
582 
583 	return count;
584 }
585 
586 static ssize_t fpdl3_output_width_show(struct device *dev,
587 				       struct device_attribute *attr, char *buf)
588 {
589 	struct video_device *vdev = to_video_device(dev);
590 	struct mgb4_vout_dev *voutdev = video_get_drvdata(vdev);
591 	s32 ret;
592 
593 	mutex_lock(&voutdev->mgbdev->i2c_lock);
594 	ret = mgb4_i2c_read_byte(&voutdev->ser, 0x5B);
595 	mutex_unlock(&voutdev->mgbdev->i2c_lock);
596 	if (ret < 0)
597 		return -EIO;
598 
599 	switch ((u8)ret & 0x03) {
600 	case 0:
601 		return sprintf(buf, "0\n");
602 	case 1:
603 		return sprintf(buf, "1\n");
604 	case 3:
605 		return sprintf(buf, "2\n");
606 	default:
607 		return -EINVAL;
608 	}
609 }
610 
611 /*
612  * FPD-Link width change is expected to be called on live streams. Video device
613  * locking/queue check is not needed.
614  */
615 static ssize_t fpdl3_output_width_store(struct device *dev,
616 					struct device_attribute *attr,
617 					const char *buf, size_t count)
618 {
619 	struct video_device *vdev = to_video_device(dev);
620 	struct mgb4_vout_dev *voutdev = video_get_drvdata(vdev);
621 	u8 i2c_data;
622 	unsigned long val;
623 	int ret;
624 
625 	ret = kstrtoul(buf, 10, &val);
626 	if (ret)
627 		return ret;
628 
629 	switch (val) {
630 	case 0: /* auto */
631 		i2c_data = 0x00;
632 		break;
633 	case 1: /* single */
634 		i2c_data = 0x01;
635 		break;
636 	case 2: /* dual */
637 		i2c_data = 0x03;
638 		break;
639 	default:
640 		return -EINVAL;
641 	}
642 
643 	mutex_lock(&voutdev->mgbdev->i2c_lock);
644 	ret = mgb4_i2c_mask_byte(&voutdev->ser, 0x5B, 0x03, i2c_data);
645 	mutex_unlock(&voutdev->mgbdev->i2c_lock);
646 	if (ret < 0)
647 		return -EIO;
648 
649 	return count;
650 }
651 
652 static ssize_t pclk_frequency_show(struct device *dev,
653 				   struct device_attribute *attr, char *buf)
654 {
655 	struct video_device *vdev = to_video_device(dev);
656 	struct mgb4_vout_dev *voutdev = video_get_drvdata(vdev);
657 
658 	return sprintf(buf, "%u\n", voutdev->freq);
659 }
660 
661 static ssize_t pclk_frequency_store(struct device *dev,
662 				    struct device_attribute *attr,
663 				    const char *buf, size_t count)
664 {
665 	struct video_device *vdev = to_video_device(dev);
666 	struct mgb4_vout_dev *voutdev = video_get_drvdata(vdev);
667 	unsigned long val;
668 	int ret;
669 	unsigned int dp;
670 
671 	ret = kstrtoul(buf, 10, &val);
672 	if (ret)
673 		return ret;
674 
675 	mutex_lock(voutdev->vdev.lock);
676 	if (vb2_is_busy(voutdev->vdev.queue)) {
677 		mutex_unlock(voutdev->vdev.lock);
678 		return -EBUSY;
679 	}
680 
681 	dp = (val > 50000) ? 1 : 0;
682 	voutdev->freq = mgb4_cmt_set_vout_freq(voutdev, val >> dp) << dp;
683 
684 	mgb4_mask_reg(&voutdev->mgbdev->video, voutdev->config->regs.config,
685 		      0x10, dp << 4);
686 	mutex_lock(&voutdev->mgbdev->i2c_lock);
687 	ret = mgb4_i2c_mask_byte(&voutdev->ser, 0x4F, 1 << 6, ((~dp) & 1) << 6);
688 	mutex_unlock(&voutdev->mgbdev->i2c_lock);
689 
690 	mutex_unlock(voutdev->vdev.lock);
691 
692 	return (ret < 0) ? -EIO : count;
693 }
694 
695 static DEVICE_ATTR_RO(output_id);
696 static DEVICE_ATTR_RW(video_source);
697 static DEVICE_ATTR_RW(display_width);
698 static DEVICE_ATTR_RW(display_height);
699 static DEVICE_ATTR_RW(frame_rate);
700 static DEVICE_ATTR_RW(hsync_polarity);
701 static DEVICE_ATTR_RW(vsync_polarity);
702 static DEVICE_ATTR_RW(de_polarity);
703 static DEVICE_ATTR_RW(pclk_frequency);
704 static DEVICE_ATTR_RW(hsync_width);
705 static DEVICE_ATTR_RW(vsync_width);
706 static DEVICE_ATTR_RW(hback_porch);
707 static DEVICE_ATTR_RW(hfront_porch);
708 static DEVICE_ATTR_RW(vback_porch);
709 static DEVICE_ATTR_RW(vfront_porch);
710 
711 static DEVICE_ATTR_RW(fpdl3_output_width);
712 
713 struct attribute *mgb4_fpdl3_out_attrs[] = {
714 	&dev_attr_output_id.attr,
715 	&dev_attr_video_source.attr,
716 	&dev_attr_display_width.attr,
717 	&dev_attr_display_height.attr,
718 	&dev_attr_frame_rate.attr,
719 	&dev_attr_hsync_polarity.attr,
720 	&dev_attr_vsync_polarity.attr,
721 	&dev_attr_de_polarity.attr,
722 	&dev_attr_pclk_frequency.attr,
723 	&dev_attr_hsync_width.attr,
724 	&dev_attr_vsync_width.attr,
725 	&dev_attr_hback_porch.attr,
726 	&dev_attr_hfront_porch.attr,
727 	&dev_attr_vback_porch.attr,
728 	&dev_attr_vfront_porch.attr,
729 	&dev_attr_fpdl3_output_width.attr,
730 	NULL
731 };
732 
733 struct attribute *mgb4_gmsl_out_attrs[] = {
734 	&dev_attr_output_id.attr,
735 	&dev_attr_video_source.attr,
736 	&dev_attr_display_width.attr,
737 	&dev_attr_display_height.attr,
738 	&dev_attr_frame_rate.attr,
739 	NULL
740 };
741