drivers/gpu/drm/openchrome/via_analog.c | 60 +++++++- drivers/gpu/drm/openchrome/via_display.c | 12 - drivers/gpu/drm/openchrome/via_display.h | 3 drivers/gpu/drm/openchrome/via_drv.h | 8 - drivers/gpu/drm/openchrome/via_fp.c | 223 ++++++++++++++++--------------- drivers/gpu/drm/openchrome/via_tmds.c | 61 +++++++- 6 files changed, 231 insertions(+), 136 deletions(-)
New commits: commit 6215de0acc85d2c989a04325115c54485da832c1 Author: Kevin Brace <kevinbr...@gmx.com> Date: Fri Nov 3 15:38:46 2017 -0700 Version bumped to 3.0.52 Made improvements in how I2C bus is used to detect the presence of a display device. Signed-off-by: Kevin Brace <kevinbr...@gmx.com> diff --git a/drivers/gpu/drm/openchrome/via_drv.h b/drivers/gpu/drm/openchrome/via_drv.h index 3b23925f8df6..6b949aff976a 100644 --- a/drivers/gpu/drm/openchrome/via_drv.h +++ b/drivers/gpu/drm/openchrome/via_drv.h @@ -30,11 +30,11 @@ #define DRIVER_AUTHOR "OpenChrome Project" #define DRIVER_NAME "openchrome" #define DRIVER_DESC "OpenChrome DRM for VIA Technologies Chrome IGP" -#define DRIVER_DATE "20171027" +#define DRIVER_DATE "20171103" #define DRIVER_MAJOR 3 #define DRIVER_MINOR 0 -#define DRIVER_PATCHLEVEL 51 +#define DRIVER_PATCHLEVEL 52 #include <linux/module.h> commit 263ace813d03d4a4a9f6324a39d597639421eb4d Author: Kevin Brace <kevinbr...@gmx.com> Date: Fri Nov 3 14:58:55 2017 -0700 Complete rewrite of I2C bus control code The previous developer's code was not well thought out, so it had to be rewritten extensively. Signed-off-by: Kevin Brace <kevinbr...@gmx.com> diff --git a/drivers/gpu/drm/openchrome/via_analog.c b/drivers/gpu/drm/openchrome/via_analog.c index 6f3fd48469f4..f4393701bb72 100644 --- a/drivers/gpu/drm/openchrome/via_analog.c +++ b/drivers/gpu/drm/openchrome/via_analog.c @@ -215,19 +215,31 @@ static const struct drm_encoder_helper_funcs via_dac_enc_helper_funcs = { static enum drm_connector_status via_analog_detect(struct drm_connector *connector, bool force) { - struct via_connector *con = container_of(connector, struct via_connector, base); + struct via_connector *con = container_of(connector, + struct via_connector, base); enum drm_connector_status ret = connector_status_disconnected; + struct i2c_adapter *i2c_bus; struct edid *edid = NULL; - drm_mode_connector_update_edid_property(connector, edid); - if (con->ddc_bus) { - edid = drm_get_edid(connector, con->ddc_bus); + DRM_DEBUG_KMS("Entered %s.\n", __func__); + + if (con->i2c_bus & VIA_I2C_BUS1) { + i2c_bus = via_find_ddc_bus(0x26); + } else { + i2c_bus = NULL; + } + + if (i2c_bus) { + edid = drm_get_edid(&con->base, i2c_bus); if (edid) { - drm_mode_connector_update_edid_property(connector, edid); + drm_mode_connector_update_edid_property(connector, + edid); kfree(edid); ret = connector_status_connected; } } + + DRM_DEBUG_KMS("Exiting %s.\n", __func__); return ret; } @@ -239,17 +251,47 @@ static const struct drm_connector_funcs via_analog_connector_funcs = { .destroy = via_connector_destroy, }; +static int via_analog_get_modes(struct drm_connector *connector) +{ + struct via_connector *con = container_of(connector, + struct via_connector, base); + int count = 0; + struct i2c_adapter *i2c_bus; + struct edid *edid = NULL; + + DRM_DEBUG_KMS("Entered %s.\n", __func__); + + if (con->i2c_bus & VIA_I2C_BUS1) { + i2c_bus = via_find_ddc_bus(0x26); + } else { + i2c_bus = NULL; + } + + if (i2c_bus) { + edid = drm_get_edid(&con->base, i2c_bus); + if (edid) { + count = drm_add_edid_modes(connector, edid); + kfree(edid); + } + } + + DRM_DEBUG_KMS("Exiting %s.\n", __func__); + return count; +} + static const struct drm_connector_helper_funcs via_analog_connector_helper_funcs = { .mode_valid = via_connector_mode_valid, - .get_modes = via_get_edid_modes, + .get_modes = via_analog_get_modes, .best_encoder = via_best_encoder, }; -void -via_analog_init(struct drm_device *dev) +void via_analog_init(struct drm_device *dev) { struct via_connector *con; struct via_encoder *enc; + struct via_device *dev_priv = dev->dev_private; + + dev_priv->analog_i2c_bus = VIA_I2C_BUS1; enc = kzalloc(sizeof(*enc) + sizeof(*con), GFP_KERNEL); if (!enc) { @@ -265,7 +307,7 @@ via_analog_init(struct drm_device *dev) drm_connector_helper_add(&con->base, &via_analog_connector_helper_funcs); drm_connector_register(&con->base); - con->ddc_bus = via_find_ddc_bus(0x26); + con->i2c_bus = dev_priv->analog_i2c_bus; con->base.doublescan_allowed = false; con->base.interlace_allowed = true; diff --git a/drivers/gpu/drm/openchrome/via_display.c b/drivers/gpu/drm/openchrome/via_display.c index cb25d3de1e8f..95eb322ab641 100644 --- a/drivers/gpu/drm/openchrome/via_display.c +++ b/drivers/gpu/drm/openchrome/via_display.c @@ -271,18 +271,6 @@ void via_encoder_cleanup(struct drm_encoder *encoder) kfree(enc); } -/* - * Shared connector routines. - */ -int -via_get_edid_modes(struct drm_connector *connector) -{ - struct via_connector *con = container_of(connector, struct via_connector, base); - struct edid *edid = drm_get_edid(&con->base, con->ddc_bus); - - return drm_add_edid_modes(connector, edid); -} - int via_connector_mode_valid(struct drm_connector *connector, struct drm_display_mode *mode) diff --git a/drivers/gpu/drm/openchrome/via_display.h b/drivers/gpu/drm/openchrome/via_display.h index 642907a83a36..fde38d90416f 100644 --- a/drivers/gpu/drm/openchrome/via_display.h +++ b/drivers/gpu/drm/openchrome/via_display.h @@ -99,7 +99,7 @@ struct via_crtc { struct via_connector { struct drm_connector base; - struct i2c_adapter *ddc_bus; + u32 i2c_bus; struct list_head props; uint32_t flags; }; @@ -180,7 +180,6 @@ extern int via_connector_set_property(struct drm_connector *connector, extern int via_connector_mode_valid(struct drm_connector *connector, struct drm_display_mode *mode); extern void via_connector_destroy(struct drm_connector *connector); -extern int via_get_edid_modes(struct drm_connector *connector); extern void via_tmds_probe(struct drm_device *dev); extern void via_fp_probe(struct drm_device *dev); diff --git a/drivers/gpu/drm/openchrome/via_drv.h b/drivers/gpu/drm/openchrome/via_drv.h index 371aee96f6ae..3b23925f8df6 100644 --- a/drivers/gpu/drm/openchrome/via_drv.h +++ b/drivers/gpu/drm/openchrome/via_drv.h @@ -209,15 +209,19 @@ struct via_device { * is needed for properly controlling its FP. */ bool is_quanta_il1; + u32 analog_i2c_bus; + bool int_tmds_presence; u32 int_tmds_di_port; u32 int_tmds_i2c_bus; bool int_fp1_presence; u32 int_fp1_di_port; + u32 int_fp1_i2c_bus; bool int_fp2_presence; u32 int_fp2_di_port; + u32 int_fp2_i2c_bus; /* Keeping track of the number of DVI connectors. */ u32 number_dvi; diff --git a/drivers/gpu/drm/openchrome/via_fp.c b/drivers/gpu/drm/openchrome/via_fp.c index 8c9c2ced8f5b..ab4bb8bd13b0 100644 --- a/drivers/gpu/drm/openchrome/via_fp.c +++ b/drivers/gpu/drm/openchrome/via_fp.c @@ -924,12 +924,26 @@ via_lcd_detect(struct drm_connector *connector, bool force) { struct via_connector *con = container_of(connector, struct via_connector, base); enum drm_connector_status ret = connector_status_disconnected; - struct edid *edid = drm_get_edid(&con->base, con->ddc_bus); + struct i2c_adapter *i2c_bus; + struct edid *edid = NULL; - if (edid) { - drm_mode_connector_update_edid_property(&con->base, edid); - kfree(edid); - ret = connector_status_connected; + DRM_DEBUG_KMS("Entered %s.\n", __func__); + + if (con->i2c_bus & VIA_I2C_BUS2) { + i2c_bus = via_find_ddc_bus(0x31); + } else if (con->i2c_bus & VIA_I2C_BUS3) { + i2c_bus = via_find_ddc_bus(0x2c); + } else { + i2c_bus = NULL; + } + + if (i2c_bus) { + edid = drm_get_edid(&con->base, i2c_bus); + if (edid) { + drm_mode_connector_update_edid_property(&con->base, edid); + kfree(edid); + ret = connector_status_connected; + } } else { struct via_device *dev_priv = connector->dev->dev_private; u8 mask = BIT(1); @@ -943,6 +957,8 @@ via_lcd_detect(struct drm_connector *connector, bool force) if (machine_is_olpc()) ret = connector_status_connected; } + + DRM_DEBUG_KMS("Exiting %s.\n", __func__); return ret; } @@ -998,35 +1014,59 @@ struct drm_connector_funcs via_lcd_connector_funcs = { static int via_lcd_get_modes(struct drm_connector *connector) { - int count = via_get_edid_modes(connector); - - /* If no edid then we detect the mode using - * the scratch pad registers. */ - if (!count) { - struct drm_display_mode *native_mode = NULL; - struct drm_device *dev = connector->dev; - - /* OLPC is very special */ - if (machine_is_olpc()) { - native_mode = drm_mode_create(dev); - - native_mode->clock = 56519; - native_mode->hdisplay = 1200; - native_mode->hsync_start = 1211; - native_mode->hsync_end = 1243; - native_mode->htotal = 1264; - native_mode->hskew = 0; - native_mode->vdisplay = 900; - native_mode->vsync_start = 901; - native_mode->vsync_end = 911; - native_mode->vtotal = 912; - native_mode->vscan = 0; - native_mode->vrefresh = 50; - native_mode->hsync = 0; + struct via_connector *con = container_of(connector, struct via_connector, base); + struct drm_device *dev = connector->dev; + struct via_device *dev_priv = dev->dev_private; + struct i2c_adapter *i2c_bus; + struct edid *edid = NULL; + struct drm_display_mode *native_mode = NULL; + u8 reg_value; + int hdisplay, vdisplay; + int count = 0; + + DRM_DEBUG_KMS("Entered %s.\n", __func__); + + /* OLPC is very special */ + if (machine_is_olpc()) { + native_mode = drm_mode_create(dev); + + native_mode->clock = 56519; + native_mode->hdisplay = 1200; + native_mode->hsync_start = 1211; + native_mode->hsync_end = 1243; + native_mode->htotal = 1264; + native_mode->hskew = 0; + native_mode->vdisplay = 900; + native_mode->vsync_start = 901; + native_mode->vsync_end = 911; + native_mode->vtotal = 912; + native_mode->vscan = 0; + native_mode->vrefresh = 50; + native_mode->hsync = 0; + + native_mode->type = DRM_MODE_TYPE_PREFERRED | + DRM_MODE_TYPE_DRIVER; + drm_mode_set_name(native_mode); + drm_mode_probed_add(connector, native_mode); + count = 1; + } else { + if (con->i2c_bus & VIA_I2C_BUS2) { + i2c_bus = via_find_ddc_bus(0x31); + } else if (con->i2c_bus & VIA_I2C_BUS3) { + i2c_bus = via_find_ddc_bus(0x2c); } else { - struct via_device *dev_priv = dev->dev_private; - u8 reg_value = (vga_rcrt(VGABASE, 0x3F) & 0x0F); - int hdisplay = 0, vdisplay = 0; + i2c_bus = NULL; + } + + if (i2c_bus) { + edid = drm_get_edid(&con->base, i2c_bus); + if (edid) { + count = drm_add_edid_modes(connector, edid); + kfree(edid); + } + } else { + reg_value = (vga_rcrt(VGABASE, 0x3F) & 0x0F); + hdisplay = vdisplay = 0; switch (reg_value) { case 0x00: @@ -1113,18 +1153,21 @@ via_lcd_get_modes(struct drm_connector *connector) break; } - if (hdisplay && vdisplay) + if (hdisplay && vdisplay) { native_mode = drm_cvt_mode(dev, hdisplay, vdisplay, 60, false, false, false); - } + } - if (native_mode) { - native_mode->type = DRM_MODE_TYPE_PREFERRED | DRM_MODE_TYPE_DRIVER; - drm_mode_set_name(native_mode); - drm_mode_probed_add(connector, native_mode); - count = 1; + if (native_mode) { + native_mode->type = DRM_MODE_TYPE_PREFERRED | DRM_MODE_TYPE_DRIVER; + drm_mode_set_name(native_mode); + drm_mode_probed_add(connector, native_mode); + count = 1; + } } } + + DRM_DEBUG_KMS("Exiting %s.\n", __func__); return count; } @@ -1363,20 +1406,40 @@ void via_fp_probe(struct drm_device *dev) break; } - DRM_DEBUG_KMS("dev_priv->int_fp1_presence: %x\n", + dev_priv->int_fp1_i2c_bus = VIA_I2C_NONE; + dev_priv->int_fp2_i2c_bus = VIA_I2C_NONE; + + if ((dev_priv->int_fp1_presence) + && (!(dev_priv->mapped_i2c_bus & VIA_I2C_BUS2))) { + dev_priv->int_fp1_i2c_bus = VIA_I2C_BUS2; + dev_priv->mapped_i2c_bus |= VIA_I2C_BUS2; + } + + if ((dev_priv->int_fp2_presence) + && (!(dev_priv->mapped_i2c_bus & VIA_I2C_BUS2))) { + dev_priv->int_fp2_i2c_bus = VIA_I2C_BUS2; + dev_priv->mapped_i2c_bus |= VIA_I2C_BUS2; + } + + DRM_DEBUG_KMS("int_fp1_presence: %x\n", dev_priv->int_fp1_presence); - DRM_DEBUG_KMS("dev_priv->int_fp1_di_port: 0x%08x\n", + DRM_DEBUG_KMS("int_fp1_di_port: 0x%08x\n", dev_priv->int_fp1_di_port); - DRM_DEBUG_KMS("dev_priv->int_fp2_presence: %x\n", + DRM_DEBUG_KMS("int_fp1_i2c_bus: 0x%08x\n", + dev_priv->int_fp1_i2c_bus); + DRM_DEBUG_KMS("int_fp2_presence: %x\n", dev_priv->int_fp2_presence); - DRM_DEBUG_KMS("dev_priv->int_fp2_di_port: 0x%08x\n", + DRM_DEBUG_KMS("int_fp2_di_port: 0x%08x\n", dev_priv->int_fp2_di_port); + DRM_DEBUG_KMS("int_fp2_i2c_bus: 0x%08x\n", + dev_priv->int_fp2_i2c_bus); + DRM_DEBUG_KMS("mapped_i2c_bus: 0x%08x\n", + dev_priv->mapped_i2c_bus); DRM_DEBUG_KMS("Exiting %s.\n", __func__); } -void -via_lvds_init(struct drm_device *dev) +void via_lvds_init(struct drm_device *dev) { struct via_device *dev_priv = dev->dev_private; bool dual_channel = false, is_msb = false; @@ -1385,6 +1448,11 @@ via_lvds_init(struct drm_device *dev) struct edid *edid; u8 reg_value; + if ((!(dev_priv->int_fp1_presence)) && + (!(dev_priv->int_fp2_presence))) { + goto exit; + } + enc = kzalloc(sizeof(*enc) + sizeof(*con), GFP_KERNEL); if (!enc) { DRM_INFO("Failed to allocate LVDS output\n"); @@ -1398,59 +1466,14 @@ via_lvds_init(struct drm_device *dev) drm_connector_helper_add(&con->base, &via_lcd_connector_helper_funcs); drm_connector_register(&con->base); - switch (dev->pdev->device) { - case PCI_DEVICE_ID_VIA_VX875: - case PCI_DEVICE_ID_VIA_VX900_VGA: - con->ddc_bus = via_find_ddc_bus(0x2C); - break; - default: - con->ddc_bus = via_find_ddc_bus(0x31); - break; - } - - edid = drm_get_edid(&con->base, con->ddc_bus); - if (!edid) { - if (!machine_is_olpc()) { - u8 mask = BIT(1); - - if (dev->pdev->device == PCI_DEVICE_ID_VIA_CLE266) - mask = BIT(3); - - /* First we have to make sure a LVDS is present */ - reg_value = (vga_rcrt(VGABASE, 0x3B) & mask); - if (!reg_value) - goto no_device; - - /* If no edid then we detect the mode using - * the scratch pad registers. */ - reg_value = (vga_rcrt(VGABASE, 0x3F) & 0x0F); - - switch (reg_value) { - case 0x04: - case 0x05: - case 0x06: - case 0x09: - case 0x0B: - case 0x0D: - case 0x0E: - case 0x0F: - dual_channel = true; - break; - - default: - break; - } - - DRM_DEBUG("panel index %x detected\n", reg_value); - - } + if (dev_priv->int_fp1_presence) { + con->i2c_bus = dev_priv->int_fp1_i2c_bus; + } else if (dev_priv->int_fp2_presence) { + con->i2c_bus = dev_priv->int_fp2_i2c_bus; } else { - /* 00 LVDS1 + LVDS2 10 = Dual channel. Other are reserved */ - if ((vga_rseq(VGABASE, 0x13) >> 6) == 2) - dual_channel = true; - - kfree(edid); + con->i2c_bus = VIA_I2C_NONE; } + con->base.doublescan_allowed = false; con->base.interlace_allowed = false; @@ -1479,10 +1502,6 @@ via_lvds_init(struct drm_device *dev) /* Put it all together */ drm_mode_connector_attach_encoder(&con->base, &enc->base); +exit: return; - -no_device: - drm_connector_unregister(&con->base); - drm_connector_cleanup(&con->base); - kfree(enc); } diff --git a/drivers/gpu/drm/openchrome/via_tmds.c b/drivers/gpu/drm/openchrome/via_tmds.c index 06f8a2effade..d9e45d254206 100644 --- a/drivers/gpu/drm/openchrome/via_tmds.c +++ b/drivers/gpu/drm/openchrome/via_tmds.c @@ -304,38 +304,82 @@ static const struct drm_encoder_helper_funcs }; static enum drm_connector_status -via_dvi_detect(struct drm_connector *connector, bool force) +via_tmds_detect(struct drm_connector *connector, bool force) { struct via_connector *con = container_of(connector, struct via_connector, base); enum drm_connector_status ret = connector_status_disconnected; + struct i2c_adapter *i2c_bus; struct edid *edid = NULL; + DRM_DEBUG_KMS("Entered %s.\n", __func__); + drm_mode_connector_update_edid_property(connector, edid); - if (con->ddc_bus) { - edid = drm_get_edid(connector, con->ddc_bus); + + if (con->i2c_bus & VIA_I2C_BUS2) { + i2c_bus = via_find_ddc_bus(0x31); + } else if (con->i2c_bus & VIA_I2C_BUS3) { + i2c_bus = via_find_ddc_bus(0x2c); + } else { + i2c_bus = NULL; + } + + if (i2c_bus) { + edid = drm_get_edid(connector, i2c_bus); if (edid) { if ((connector->connector_type == DRM_MODE_CONNECTOR_DVIA) ^ - (edid->input & DRM_EDID_INPUT_DIGITAL)) { + (edid->input & DRM_EDID_INPUT_DIGITAL)) { drm_mode_connector_update_edid_property(connector, edid); ret = connector_status_connected; } + kfree(edid); } } + + DRM_DEBUG_KMS("Exiting %s.\n", __func__); return ret; } static const struct drm_connector_funcs via_dvi_connector_funcs = { .dpms = drm_helper_connector_dpms, - .detect = via_dvi_detect, + .detect = via_tmds_detect, .fill_modes = drm_helper_probe_single_connector_modes, .set_property = via_connector_set_property, .destroy = via_connector_destroy, }; +static int via_tmds_get_modes(struct drm_connector *connector) +{ + struct via_connector *con = container_of(connector, struct via_connector, base); + struct i2c_adapter *i2c_bus; + struct edid *edid = NULL; + int count = 0; + + DRM_DEBUG_KMS("Entered %s.\n", __func__); + + if (con->i2c_bus & VIA_I2C_BUS2) { + i2c_bus = via_find_ddc_bus(0x31); + } else if (con->i2c_bus & VIA_I2C_BUS3) { + i2c_bus = via_find_ddc_bus(0x2c); + } else { + i2c_bus = NULL; + } + + if (i2c_bus) { + edid = drm_get_edid(&con->base, i2c_bus); + if (edid) { + count = drm_add_edid_modes(connector, edid); + kfree(edid); + } + } + + DRM_DEBUG_KMS("Exiting %s.\n", __func__); + return count; +} + static const struct drm_connector_helper_funcs via_dvi_connector_helper_funcs = { .mode_valid = via_connector_mode_valid, - .get_modes = via_get_edid_modes, + .get_modes = via_tmds_get_modes, .best_encoder = via_best_encoder, }; @@ -423,7 +467,6 @@ void via_tmds_init(struct drm_device *dev) struct via_device *dev_priv = dev->dev_private; struct via_connector *con; struct via_encoder *enc; - int i2c_port = 0x31; DRM_DEBUG_KMS("Entered %s.\n", __func__); @@ -459,7 +502,7 @@ void via_tmds_init(struct drm_device *dev) drm_connector_helper_add(&con->base, &via_dvi_connector_helper_funcs); drm_connector_register(&con->base); - con->ddc_bus = via_find_ddc_bus(i2c_port); + con->i2c_bus = dev_priv->int_tmds_i2c_bus; con->base.doublescan_allowed = false; con->base.interlace_allowed = true; INIT_LIST_HEAD(&con->props); @@ -473,7 +516,7 @@ void via_tmds_init(struct drm_device *dev) drm_connector_helper_add(&con->base, &via_dvi_connector_helper_funcs); drm_connector_register(&con->base); - con->ddc_bus = via_find_ddc_bus(i2c_port); + con->i2c_bus = dev_priv->int_tmds_i2c_bus; con->base.doublescan_allowed = false; con->base.interlace_allowed = true; INIT_LIST_HEAD(&con->props); _______________________________________________ Openchrome-devel mailing list Openchrome-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/openchrome-devel