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_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 */
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 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
hsync_width_show(struct device * dev,struct device_attribute * attr,char * buf)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 */
hsync_width_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)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
vsync_width_show(struct device * dev,struct device_attribute * attr,char * buf)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 */
vsync_width_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)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
hback_porch_show(struct device * dev,struct device_attribute * attr,char * buf)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 */
hback_porch_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)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
vback_porch_show(struct device * dev,struct device_attribute * attr,char * buf)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 */
vback_porch_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)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
hfront_porch_show(struct device * dev,struct device_attribute * attr,char * buf)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 */
hfront_porch_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)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
vfront_porch_show(struct device * dev,struct device_attribute * attr,char * buf)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 */
vfront_porch_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)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
hsync_polarity_show(struct device * dev,struct device_attribute * attr,char * buf)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 */
hsync_polarity_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)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
vsync_polarity_show(struct device * dev,struct device_attribute * attr,char * buf)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 */
vsync_polarity_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)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
de_polarity_show(struct device * dev,struct device_attribute * attr,char * buf)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 */
de_polarity_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)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
fpdl3_output_width_show(struct device * dev,struct device_attribute * attr,char * buf)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 */
fpdl3_output_width_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)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
pclk_frequency_show(struct device * dev,struct device_attribute * attr,char * buf)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
pclk_frequency_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)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