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