9
9
* the Free Software Foundation.
10
10
*/
11
11
12
+ #include <linux/gpio/consumer.h>
12
13
#include <linux/i2c.h>
13
14
#include <linux/module.h>
14
15
#include <linux/platform_device.h>
@@ -44,23 +45,40 @@ struct panel_drv_data {
44
45
struct videomode vm ;
45
46
46
47
struct i2c_adapter * i2c_adapter ;
48
+
49
+ struct gpio_desc * hpd_gpio ;
50
+
51
+ void (* hpd_cb )(void * cb_data , enum drm_connector_status status );
52
+ void * hpd_cb_data ;
53
+ bool hpd_enabled ;
54
+ /* mutex for hpd fields above */
55
+ struct mutex hpd_lock ;
47
56
};
48
57
49
58
#define to_panel_data (x ) container_of(x, struct panel_drv_data, dssdev)
50
59
51
60
static int dvic_connect (struct omap_dss_device * dssdev )
52
61
{
53
62
struct panel_drv_data * ddata = to_panel_data (dssdev );
54
- struct omap_dss_device * in = ddata -> in ;
63
+ struct omap_dss_device * in ;
55
64
int r ;
56
65
57
66
if (omapdss_device_is_connected (dssdev ))
58
67
return 0 ;
59
68
69
+ in = omapdss_of_find_source_for_first_ep (dssdev -> dev -> of_node );
70
+ if (IS_ERR (in )) {
71
+ dev_err (dssdev -> dev , "failed to find video source\n" );
72
+ return PTR_ERR (in );
73
+ }
74
+
60
75
r = in -> ops .dvi -> connect (in , dssdev );
61
- if (r )
76
+ if (r ) {
77
+ omap_dss_put_device (in );
62
78
return r ;
79
+ }
63
80
81
+ ddata -> in = in ;
64
82
return 0 ;
65
83
}
66
84
@@ -73,6 +91,9 @@ static void dvic_disconnect(struct omap_dss_device *dssdev)
73
91
return ;
74
92
75
93
in -> ops .dvi -> disconnect (in , dssdev );
94
+
95
+ omap_dss_put_device (in );
96
+ ddata -> in = NULL ;
76
97
}
77
98
78
99
static int dvic_enable (struct omap_dss_device * dssdev )
@@ -177,6 +198,9 @@ static int dvic_read_edid(struct omap_dss_device *dssdev,
177
198
struct panel_drv_data * ddata = to_panel_data (dssdev );
178
199
int r , l , bytes_read ;
179
200
201
+ if (ddata -> hpd_gpio && !gpiod_get_value_cansleep (ddata -> hpd_gpio ))
202
+ return - ENODEV ;
203
+
180
204
if (!ddata -> i2c_adapter )
181
205
return - ENODEV ;
182
206
@@ -208,6 +232,9 @@ static bool dvic_detect(struct omap_dss_device *dssdev)
208
232
unsigned char out ;
209
233
int r ;
210
234
235
+ if (ddata -> hpd_gpio )
236
+ return gpiod_get_value_cansleep (ddata -> hpd_gpio );
237
+
211
238
if (!ddata -> i2c_adapter )
212
239
return true;
213
240
@@ -216,6 +243,60 @@ static bool dvic_detect(struct omap_dss_device *dssdev)
216
243
return r == 0 ;
217
244
}
218
245
246
+ static int dvic_register_hpd_cb (struct omap_dss_device * dssdev ,
247
+ void (* cb )(void * cb_data ,
248
+ enum drm_connector_status status ),
249
+ void * cb_data )
250
+ {
251
+ struct panel_drv_data * ddata = to_panel_data (dssdev );
252
+
253
+ if (!ddata -> hpd_gpio )
254
+ return - ENOTSUPP ;
255
+
256
+ mutex_lock (& ddata -> hpd_lock );
257
+ ddata -> hpd_cb = cb ;
258
+ ddata -> hpd_cb_data = cb_data ;
259
+ mutex_unlock (& ddata -> hpd_lock );
260
+ return 0 ;
261
+ }
262
+
263
+ static void dvic_unregister_hpd_cb (struct omap_dss_device * dssdev )
264
+ {
265
+ struct panel_drv_data * ddata = to_panel_data (dssdev );
266
+
267
+ if (!ddata -> hpd_gpio )
268
+ return ;
269
+
270
+ mutex_lock (& ddata -> hpd_lock );
271
+ ddata -> hpd_cb = NULL ;
272
+ ddata -> hpd_cb_data = NULL ;
273
+ mutex_unlock (& ddata -> hpd_lock );
274
+ }
275
+
276
+ static void dvic_enable_hpd (struct omap_dss_device * dssdev )
277
+ {
278
+ struct panel_drv_data * ddata = to_panel_data (dssdev );
279
+
280
+ if (!ddata -> hpd_gpio )
281
+ return ;
282
+
283
+ mutex_lock (& ddata -> hpd_lock );
284
+ ddata -> hpd_enabled = true;
285
+ mutex_unlock (& ddata -> hpd_lock );
286
+ }
287
+
288
+ static void dvic_disable_hpd (struct omap_dss_device * dssdev )
289
+ {
290
+ struct panel_drv_data * ddata = to_panel_data (dssdev );
291
+
292
+ if (!ddata -> hpd_gpio )
293
+ return ;
294
+
295
+ mutex_lock (& ddata -> hpd_lock );
296
+ ddata -> hpd_enabled = false;
297
+ mutex_unlock (& ddata -> hpd_lock );
298
+ }
299
+
219
300
static struct omap_dss_driver dvic_driver = {
220
301
.connect = dvic_connect ,
221
302
.disconnect = dvic_disconnect ,
@@ -229,31 +310,67 @@ static struct omap_dss_driver dvic_driver = {
229
310
230
311
.read_edid = dvic_read_edid ,
231
312
.detect = dvic_detect ,
313
+
314
+ .register_hpd_cb = dvic_register_hpd_cb ,
315
+ .unregister_hpd_cb = dvic_unregister_hpd_cb ,
316
+ .enable_hpd = dvic_enable_hpd ,
317
+ .disable_hpd = dvic_disable_hpd ,
232
318
};
233
319
320
+ static irqreturn_t dvic_hpd_isr (int irq , void * data )
321
+ {
322
+ struct panel_drv_data * ddata = data ;
323
+
324
+ mutex_lock (& ddata -> hpd_lock );
325
+ if (ddata -> hpd_enabled && ddata -> hpd_cb ) {
326
+ enum drm_connector_status status ;
327
+
328
+ if (dvic_detect (& ddata -> dssdev ))
329
+ status = connector_status_connected ;
330
+ else
331
+ status = connector_status_disconnected ;
332
+
333
+ ddata -> hpd_cb (ddata -> hpd_cb_data , status );
334
+ }
335
+ mutex_unlock (& ddata -> hpd_lock );
336
+
337
+ return IRQ_HANDLED ;
338
+ }
339
+
234
340
static int dvic_probe_of (struct platform_device * pdev )
235
341
{
236
342
struct panel_drv_data * ddata = platform_get_drvdata (pdev );
237
343
struct device_node * node = pdev -> dev .of_node ;
238
- struct omap_dss_device * in ;
239
344
struct device_node * adapter_node ;
240
345
struct i2c_adapter * adapter ;
346
+ struct gpio_desc * gpio ;
347
+ int r ;
241
348
242
- in = omapdss_of_find_source_for_first_ep ( node );
243
- if (IS_ERR (in )) {
244
- dev_err (& pdev -> dev , "failed to find video source \n" );
245
- return PTR_ERR (in );
349
+ gpio = devm_gpiod_get_optional ( & pdev -> dev , "hpd" , GPIOD_IN );
350
+ if (IS_ERR (gpio )) {
351
+ dev_err (& pdev -> dev , "failed to parse HPD gpio \n" );
352
+ return PTR_ERR (gpio );
246
353
}
247
354
248
- ddata -> in = in ;
355
+ ddata -> hpd_gpio = gpio ;
356
+
357
+ mutex_init (& ddata -> hpd_lock );
358
+
359
+ if (ddata -> hpd_gpio ) {
360
+ r = devm_request_threaded_irq (& pdev -> dev ,
361
+ gpiod_to_irq (ddata -> hpd_gpio ), NULL , dvic_hpd_isr ,
362
+ IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING | IRQF_ONESHOT ,
363
+ "DVI HPD" , ddata );
364
+ if (r )
365
+ return r ;
366
+ }
249
367
250
368
adapter_node = of_parse_phandle (node , "ddc-i2c-bus" , 0 );
251
369
if (adapter_node ) {
252
370
adapter = of_get_i2c_adapter_by_node (adapter_node );
253
371
of_node_put (adapter_node );
254
372
if (adapter == NULL ) {
255
373
dev_err (& pdev -> dev , "failed to parse ddc-i2c-bus\n" );
256
- omap_dss_put_device (ddata -> in );
257
374
return - EPROBE_DEFER ;
258
375
}
259
376
@@ -275,9 +392,6 @@ static int dvic_probe(struct platform_device *pdev)
275
392
276
393
platform_set_drvdata (pdev , ddata );
277
394
278
- if (!pdev -> dev .of_node )
279
- return - ENODEV ;
280
-
281
395
r = dvic_probe_of (pdev );
282
396
if (r )
283
397
return r ;
@@ -300,9 +414,8 @@ static int dvic_probe(struct platform_device *pdev)
300
414
return 0 ;
301
415
302
416
err_reg :
303
- omap_dss_put_device (ddata -> in );
304
-
305
417
i2c_put_adapter (ddata -> i2c_adapter );
418
+ mutex_destroy (& ddata -> hpd_lock );
306
419
307
420
return r ;
308
421
}
@@ -311,17 +424,16 @@ static int __exit dvic_remove(struct platform_device *pdev)
311
424
{
312
425
struct panel_drv_data * ddata = platform_get_drvdata (pdev );
313
426
struct omap_dss_device * dssdev = & ddata -> dssdev ;
314
- struct omap_dss_device * in = ddata -> in ;
315
427
316
428
omapdss_unregister_display (& ddata -> dssdev );
317
429
318
430
dvic_disable (dssdev );
319
431
dvic_disconnect (dssdev );
320
432
321
- omap_dss_put_device (in );
322
-
323
433
i2c_put_adapter (ddata -> i2c_adapter );
324
434
435
+ mutex_destroy (& ddata -> hpd_lock );
436
+
325
437
return 0 ;
326
438
}
327
439
0 commit comments