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