xref: /linux/drivers/media/pci/mgb4/mgb4_sysfs_in.c (revision 4b132aacb0768ac1e652cf517097ea6f237214b9)
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 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.signal);
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.signal2);
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.signal);
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.signal);
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.signal2);
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.signal2);
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 };
773