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
loopin_cnt(struct mgb4_vin_dev * vindev)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
is_busy(struct video_device * dev)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
output_id_show(struct device * dev,struct device_attribute * attr,char * buf)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
video_source_show(struct device * dev,struct device_attribute * attr,char * buf)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 */
video_source_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)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
display_width_show(struct device * dev,struct device_attribute * attr,char * buf)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
display_width_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)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
display_height_show(struct device * dev,struct device_attribute * attr,char * buf)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
display_height_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)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
frame_rate_show(struct device * dev,struct device_attribute * attr,char * buf)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 */
frame_rate_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)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
hsync_width_show(struct device * dev,struct device_attribute * attr,char * buf)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 */
hsync_width_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)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
vsync_width_show(struct device * dev,struct device_attribute * attr,char * buf)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 */
vsync_width_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)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
hback_porch_show(struct device * dev,struct device_attribute * attr,char * buf)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 */
hback_porch_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)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
vback_porch_show(struct device * dev,struct device_attribute * attr,char * buf)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 */
vback_porch_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)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
hfront_porch_show(struct device * dev,struct device_attribute * attr,char * buf)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 */
hfront_porch_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)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
vfront_porch_show(struct device * dev,struct device_attribute * attr,char * buf)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 */
vfront_porch_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)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
hsync_polarity_show(struct device * dev,struct device_attribute * attr,char * buf)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 */
hsync_polarity_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)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
vsync_polarity_show(struct device * dev,struct device_attribute * attr,char * buf)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 */
vsync_polarity_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)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
de_polarity_show(struct device * dev,struct device_attribute * attr,char * buf)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 */
de_polarity_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)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
fpdl3_output_width_show(struct device * dev,struct device_attribute * attr,char * buf)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 */
fpdl3_output_width_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)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
pclk_frequency_show(struct device * dev,struct device_attribute * attr,char * buf)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
pclk_frequency_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)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