44
55#include <linux/firmware.h>
66#include <linux/delay.h>
7+
8+ #include <drm/drm_atomic_state_helper.h>
9+ #include <drm/drm_edid.h>
10+ #include <drm/drm_modeset_helper_vtables.h>
711#include <drm/drm_print.h>
12+ #include <drm/drm_probe_helper.h>
13+
814#include "ast_drv.h"
915
10- bool ast_astdp_is_connected (struct ast_device * ast )
16+ static bool ast_astdp_is_connected (struct ast_device * ast )
1117{
1218 if (!ast_get_index_reg_mask (ast , AST_IO_VGACRI , 0xDF , AST_IO_VGACRDF_HPD ))
1319 return false;
1420 return true;
1521}
1622
17- int ast_astdp_read_edid (struct drm_device * dev , u8 * ediddata )
23+ static int ast_astdp_read_edid (struct drm_device * dev , u8 * ediddata )
1824{
1925 struct ast_device * ast = to_ast_device (dev );
2026 int ret = 0 ;
@@ -120,7 +126,7 @@ int ast_dp_launch(struct ast_device *ast)
120126 return 0 ;
121127}
122128
123- bool ast_dp_power_is_on (struct ast_device * ast )
129+ static bool ast_dp_power_is_on (struct ast_device * ast )
124130{
125131 u8 vgacre3 ;
126132
@@ -129,7 +135,7 @@ bool ast_dp_power_is_on(struct ast_device *ast)
129135 return !(vgacre3 & AST_DP_PHY_SLEEP );
130136}
131137
132- void ast_dp_power_on_off (struct drm_device * dev , bool on )
138+ static void ast_dp_power_on_off (struct drm_device * dev , bool on )
133139{
134140 struct ast_device * ast = to_ast_device (dev );
135141 // Read and Turn off DP PHY sleep
@@ -143,7 +149,7 @@ void ast_dp_power_on_off(struct drm_device *dev, bool on)
143149 ast_set_index_reg_mask (ast , AST_IO_VGACRI , 0xE3 , (u8 ) ~AST_DP_PHY_SLEEP , bE3 );
144150}
145151
146- void ast_dp_link_training (struct ast_device * ast )
152+ static void ast_dp_link_training (struct ast_device * ast )
147153{
148154 struct drm_device * dev = & ast -> base ;
149155 int i ;
@@ -161,7 +167,7 @@ void ast_dp_link_training(struct ast_device *ast)
161167 drm_err (dev , "Link training failed\n" );
162168}
163169
164- void ast_dp_set_on_off (struct drm_device * dev , bool on )
170+ static void ast_dp_set_on_off (struct drm_device * dev , bool on )
165171{
166172 struct ast_device * ast = to_ast_device (dev );
167173 u8 video_on_off = on ;
@@ -180,7 +186,7 @@ void ast_dp_set_on_off(struct drm_device *dev, bool on)
180186 }
181187}
182188
183- void ast_dp_set_mode (struct drm_crtc * crtc , struct ast_vbios_mode_info * vbios_mode )
189+ static void ast_dp_set_mode (struct drm_crtc * crtc , struct ast_vbios_mode_info * vbios_mode )
184190{
185191 struct ast_device * ast = to_ast_device (crtc -> dev );
186192
@@ -253,3 +259,197 @@ void ast_dp_set_mode(struct drm_crtc *crtc, struct ast_vbios_mode_info *vbios_mo
253259 ast_set_index_reg_mask (ast , AST_IO_VGACRI , 0xE1 , ASTDP_AND_CLEAR_MASK , ASTDP_MISC1 );
254260 ast_set_index_reg_mask (ast , AST_IO_VGACRI , 0xE2 , ASTDP_AND_CLEAR_MASK , ModeIdx );
255261}
262+
263+ static void ast_wait_for_vretrace (struct ast_device * ast )
264+ {
265+ unsigned long timeout = jiffies + HZ ;
266+ u8 vgair1 ;
267+
268+ do {
269+ vgair1 = ast_io_read8 (ast , AST_IO_VGAIR1_R );
270+ } while (!(vgair1 & AST_IO_VGAIR1_VREFRESH ) && time_before (jiffies , timeout ));
271+ }
272+
273+ /*
274+ * Encoder
275+ */
276+
277+ static const struct drm_encoder_funcs ast_astdp_encoder_funcs = {
278+ .destroy = drm_encoder_cleanup ,
279+ };
280+
281+ static void ast_astdp_encoder_helper_atomic_mode_set (struct drm_encoder * encoder ,
282+ struct drm_crtc_state * crtc_state ,
283+ struct drm_connector_state * conn_state )
284+ {
285+ struct drm_crtc * crtc = crtc_state -> crtc ;
286+ struct ast_crtc_state * ast_crtc_state = to_ast_crtc_state (crtc_state );
287+ struct ast_vbios_mode_info * vbios_mode_info = & ast_crtc_state -> vbios_mode_info ;
288+
289+ ast_dp_set_mode (crtc , vbios_mode_info );
290+ }
291+
292+ static void ast_astdp_encoder_helper_atomic_enable (struct drm_encoder * encoder ,
293+ struct drm_atomic_state * state )
294+ {
295+ struct drm_device * dev = encoder -> dev ;
296+ struct ast_device * ast = to_ast_device (dev );
297+
298+ ast_dp_power_on_off (dev , AST_DP_POWER_ON );
299+ ast_dp_link_training (ast );
300+
301+ ast_wait_for_vretrace (ast );
302+ ast_dp_set_on_off (dev , 1 );
303+ }
304+
305+ static void ast_astdp_encoder_helper_atomic_disable (struct drm_encoder * encoder ,
306+ struct drm_atomic_state * state )
307+ {
308+ struct drm_device * dev = encoder -> dev ;
309+
310+ ast_dp_set_on_off (dev , 0 );
311+ ast_dp_power_on_off (dev , AST_DP_POWER_OFF );
312+ }
313+
314+ static const struct drm_encoder_helper_funcs ast_astdp_encoder_helper_funcs = {
315+ .atomic_mode_set = ast_astdp_encoder_helper_atomic_mode_set ,
316+ .atomic_enable = ast_astdp_encoder_helper_atomic_enable ,
317+ .atomic_disable = ast_astdp_encoder_helper_atomic_disable ,
318+ };
319+
320+ /*
321+ * Connector
322+ */
323+
324+ static int ast_astdp_connector_helper_get_modes (struct drm_connector * connector )
325+ {
326+ void * edid ;
327+ struct drm_device * dev = connector -> dev ;
328+ struct ast_device * ast = to_ast_device (dev );
329+
330+ int succ ;
331+ int count ;
332+
333+ edid = kmalloc (EDID_LENGTH , GFP_KERNEL );
334+ if (!edid )
335+ goto err_drm_connector_update_edid_property ;
336+
337+ /*
338+ * Protect access to I/O registers from concurrent modesetting
339+ * by acquiring the I/O-register lock.
340+ */
341+ mutex_lock (& ast -> modeset_lock );
342+
343+ succ = ast_astdp_read_edid (connector -> dev , edid );
344+ if (succ < 0 )
345+ goto err_mutex_unlock ;
346+
347+ mutex_unlock (& ast -> modeset_lock );
348+
349+ drm_connector_update_edid_property (connector , edid );
350+ count = drm_add_edid_modes (connector , edid );
351+ kfree (edid );
352+
353+ return count ;
354+
355+ err_mutex_unlock :
356+ mutex_unlock (& ast -> modeset_lock );
357+ kfree (edid );
358+ err_drm_connector_update_edid_property :
359+ drm_connector_update_edid_property (connector , NULL );
360+ return 0 ;
361+ }
362+
363+ static int ast_astdp_connector_helper_detect_ctx (struct drm_connector * connector ,
364+ struct drm_modeset_acquire_ctx * ctx ,
365+ bool force )
366+ {
367+ struct drm_device * dev = connector -> dev ;
368+ struct ast_device * ast = to_ast_device (connector -> dev );
369+ enum drm_connector_status status = connector_status_disconnected ;
370+ struct drm_connector_state * connector_state = connector -> state ;
371+ bool is_active = false;
372+
373+ mutex_lock (& ast -> modeset_lock );
374+
375+ if (connector_state && connector_state -> crtc ) {
376+ struct drm_crtc_state * crtc_state = connector_state -> crtc -> state ;
377+
378+ if (crtc_state && crtc_state -> active )
379+ is_active = true;
380+ }
381+
382+ if (!is_active && !ast_dp_power_is_on (ast )) {
383+ ast_dp_power_on_off (dev , true);
384+ msleep (50 );
385+ }
386+
387+ if (ast_astdp_is_connected (ast ))
388+ status = connector_status_connected ;
389+
390+ if (!is_active && status == connector_status_disconnected )
391+ ast_dp_power_on_off (dev , false);
392+
393+ mutex_unlock (& ast -> modeset_lock );
394+
395+ return status ;
396+ }
397+
398+ static const struct drm_connector_helper_funcs ast_astdp_connector_helper_funcs = {
399+ .get_modes = ast_astdp_connector_helper_get_modes ,
400+ .detect_ctx = ast_astdp_connector_helper_detect_ctx ,
401+ };
402+
403+ static const struct drm_connector_funcs ast_astdp_connector_funcs = {
404+ .reset = drm_atomic_helper_connector_reset ,
405+ .fill_modes = drm_helper_probe_single_connector_modes ,
406+ .destroy = drm_connector_cleanup ,
407+ .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state ,
408+ .atomic_destroy_state = drm_atomic_helper_connector_destroy_state ,
409+ };
410+
411+ static int ast_astdp_connector_init (struct drm_device * dev , struct drm_connector * connector )
412+ {
413+ int ret ;
414+
415+ ret = drm_connector_init (dev , connector , & ast_astdp_connector_funcs ,
416+ DRM_MODE_CONNECTOR_DisplayPort );
417+ if (ret )
418+ return ret ;
419+
420+ drm_connector_helper_add (connector , & ast_astdp_connector_helper_funcs );
421+
422+ connector -> interlace_allowed = 0 ;
423+ connector -> doublescan_allowed = 0 ;
424+
425+ connector -> polled = DRM_CONNECTOR_POLL_CONNECT | DRM_CONNECTOR_POLL_DISCONNECT ;
426+
427+ return 0 ;
428+ }
429+
430+ int ast_astdp_output_init (struct ast_device * ast )
431+ {
432+ struct drm_device * dev = & ast -> base ;
433+ struct drm_crtc * crtc = & ast -> crtc ;
434+ struct drm_encoder * encoder = & ast -> output .astdp .encoder ;
435+ struct drm_connector * connector = & ast -> output .astdp .connector ;
436+ int ret ;
437+
438+ ret = drm_encoder_init (dev , encoder , & ast_astdp_encoder_funcs ,
439+ DRM_MODE_ENCODER_TMDS , NULL );
440+ if (ret )
441+ return ret ;
442+ drm_encoder_helper_add (encoder , & ast_astdp_encoder_helper_funcs );
443+
444+ encoder -> possible_crtcs = drm_crtc_mask (crtc );
445+
446+ ret = ast_astdp_connector_init (dev , connector );
447+ if (ret )
448+ return ret ;
449+
450+ ret = drm_connector_attach_encoder (connector , encoder );
451+ if (ret )
452+ return ret ;
453+
454+ return 0 ;
455+ }
0 commit comments