diff --git a/sys/dev/drm/intel_iic.c b/sys/dev/drm/intel_iic.c index 8a45971..61ffb41 100644 --- a/sys/dev/drm/intel_iic.c +++ b/sys/dev/drm/intel_iic.c @@ -59,9 +59,10 @@ #include "dev/drm/i915_drv.h" #include "dev/drm/intel_drv.h" #include +#include +#include #include "iicbus_if.h" #include "iicbb_if.h" -#include static int intel_iic_quirk_xfer(device_t idev, struct iic_msg *msgs, int nmsgs); static void intel_teardown_gmbus_m(struct drm_device *dev, int m); @@ -72,6 +73,7 @@ static void intel_teardown_gmbus_m(struct drm_device *dev, int m); struct intel_iic_softc { struct drm_device *drm_dev; + device_t iic_dev; bool force_bit_dev; char name[32]; uint32_t reg; @@ -368,18 +370,25 @@ intel_iic_quirk_xfer(device_t idev, struct iic_msg *msgs, int nmsgs) struct intel_iic_softc *sc; struct drm_i915_private *dev_priv; int ret; + int i; sc = device_get_softc(idev); dev_priv = sc->drm_dev->dev_private; iicbus_reset(idev, 0, 0, NULL); intel_iic_quirk_set(dev_priv, TRUE); - IICBB_SETSDA(device_get_parent(idev), 1); - IICBB_SETSCL(device_get_parent(idev), 1); + IICBB_SETSDA(device_get_parent(device_get_parent(idev)), 1); + IICBB_SETSCL(device_get_parent(device_get_parent(idev)), 1); DELAY(I2C_RISEFALL_TIME); + /* convert slave addresses to format expected by iicbb */ + for (i = 0; i < nmsgs; i++) + msgs[i].slave <<= 1; ret = iicbus_transfer(idev, msgs, nmsgs); - IICBB_SETSDA(device_get_parent(idev), 1); - IICBB_SETSCL(device_get_parent(idev), 1); + /* restore just in case */ + for (i = 0; i < nmsgs; i++) + msgs[i].slave >>= 1; + IICBB_SETSDA(device_get_parent(device_get_parent(idev)), 1); + IICBB_SETSCL(device_get_parent(device_get_parent(idev)), 1); intel_iic_quirk_set(dev_priv, FALSE); return (ret); @@ -426,6 +435,12 @@ intel_gmbus_attach(device_t idev) sc->force_bit_dev = TRUE; } + /* add bus interface device */ + sc->iic_dev = device_add_child(idev, "iicbus", -1); + if (sc->iic_dev == NULL) + return (ENXIO); + bus_generic_attach(idev); + return (0); } @@ -434,12 +449,18 @@ intel_gmbus_detach(device_t idev) { struct intel_iic_softc *sc; struct drm_i915_private *dev_priv; + device_t child; int u; sc = device_get_softc(idev); u = device_get_unit(idev); dev_priv = sc->drm_dev->dev_private; + child = sc->iic_dev; + bus_generic_detach(idev); + if (child) + device_delete_child(idev, child); + return (0); } @@ -467,13 +488,26 @@ intel_iicbb_attach(device_t idev) sc->reg0 = pin | GMBUS_RATE_100KHZ; + /* add generic bit-banging code */ + sc->iic_dev = device_add_child(idev, "iicbb", -1); + if (sc->iic_dev == NULL) + return (ENXIO); + bus_generic_attach(idev); + return (0); } static int intel_iicbb_detach(device_t idev) { + struct intel_iic_softc *sc; + device_t child; + sc = device_get_softc(idev); + child = sc->iic_dev; + bus_generic_detach(idev); + if (child) + device_delete_child(idev, child); return (0); } @@ -493,6 +527,7 @@ static driver_t intel_gmbus_driver = { static devclass_t intel_gmbus_devclass; DRIVER_MODULE_ORDERED(intel_gmbus, drm, intel_gmbus_driver, intel_gmbus_devclass, 0, 0, SI_ORDER_FIRST); +DRIVER_MODULE(iicbus, intel_gmbus, iicbus_driver, iicbus_devclass, 0, 0); static device_method_t intel_iicbb_methods[] = { DEVMETHOD(device_probe, intel_iicbb_probe), @@ -514,77 +549,13 @@ static driver_t intel_iicbb_driver = { static devclass_t intel_iicbb_devclass; DRIVER_MODULE_ORDERED(intel_iicbb, drm, intel_iicbb_driver, intel_iicbb_devclass, 0, 0, SI_ORDER_FIRST); - -static int -intel_ddc_port_probe(device_t idev) -{ - - return (BUS_PROBE_DEFAULT); -} - -static int -intel_ddc_port_attach(device_t idev) -{ - struct intel_iic_softc *sc; - struct drm_i915_private *dev_priv; - int pin; - - sc = device_get_softc(idev); - sc->drm_dev = device_get_softc(device_get_parent( - device_get_parent(idev))); - dev_priv = sc->drm_dev->dev_private; - pin = device_get_unit(idev); - - snprintf(sc->name, sizeof(sc->name), "gmbus port %s", gpio_names[pin]); - device_set_desc(idev, sc->name); - - /* By default use a conservative clock rate */ - sc->reg0 = pin | GMBUS_RATE_100KHZ; - - return (0); -} - -static int -intel_ddc_port_detach(device_t idev) -{ - - return (0); -} - -static device_method_t intel_ddc_port_methods[] = { - DEVMETHOD(device_probe, intel_ddc_port_probe), - DEVMETHOD(device_attach, intel_ddc_port_attach), - DEVMETHOD(device_detach, intel_ddc_port_detach), - { 0, 0 } -}; -static driver_t intel_ddc_port_driver = { - "intel_ddc_port", - intel_ddc_port_methods, - sizeof(struct intel_iic_softc) -}; -static devclass_t intel_ddc_port_devclass; -DRIVER_MODULE_ORDERED(intel_ddc_port, intel_gmbus, intel_ddc_port_driver, - intel_ddc_port_devclass, 0, 0, SI_ORDER_SECOND); - -static device_method_t intel_ddc_bb_port_methods[] = { - DEVMETHOD(device_probe, intel_ddc_port_probe), - DEVMETHOD(device_attach, intel_ddc_port_attach), - DEVMETHOD(device_detach, intel_ddc_port_detach), - { 0, 0 } -}; -static driver_t intel_ddc_bb_port_driver = { - "intel_ddc_bb_port", - intel_ddc_bb_port_methods, - sizeof(struct intel_iic_softc) -}; -static devclass_t intel_ddc_bb_port_devclass; -DRIVER_MODULE_ORDERED(intel_ddc_bb_port, intel_iicbb, intel_ddc_bb_port_driver, - intel_ddc_bb_port_devclass, 0, 0, SI_ORDER_SECOND); +DRIVER_MODULE(iicbb, intel_iicbb, iicbb_driver, iicbb_devclass, 0, 0); int intel_setup_gmbus(struct drm_device *dev) { struct drm_i915_private *dev_priv; + device_t iic_dev; int i, ret; dev_priv = dev->dev_private; @@ -624,20 +595,19 @@ intel_setup_gmbus(struct drm_device *dev) goto err; } - dev_priv->bbbus[i] = device_add_child(dev_priv->bbbus_bridge[i], - "intel_ddc_bb_port", i); - if (dev_priv->bbbus[i] == NULL) { - DRM_ERROR("bbbus port %d creation error\n", i); - ret = ENXIO; + iic_dev = device_find_child(dev_priv->bbbus_bridge[i], "iicbb", -1); + if (iic_dev == NULL) { + DRM_ERROR("bbbus bridge doesn't have iicbb child\n"); goto err; } - device_quiet(dev_priv->bbbus[i]); - ret = device_probe_and_attach(dev_priv->bbbus[i]); - if (ret != 0) { - DRM_ERROR("bbbus port %d attach error %d\n", i, ret); + iic_dev = device_find_child(iic_dev, "iicbus", -1); + if (iic_dev == NULL) { + DRM_ERROR("bbbus bridge doesn't have iicbus grandchild\n"); goto err; } + dev_priv->bbbus[i] = iic_dev; + dev_priv->gmbus_bridge[i] = device_add_child(dev->device, "intel_gmbus", i); if (dev_priv->gmbus_bridge[i] == NULL) { @@ -654,19 +624,13 @@ intel_setup_gmbus(struct drm_device *dev) goto err; } - dev_priv->gmbus[i] = device_add_child(dev_priv->gmbus_bridge[i], - "intel_ddc_port", i); - if (dev_priv->gmbus[i] == NULL) { - DRM_ERROR("gmbus port %d creation error\n", i); - ret = ENXIO; - goto err; - } - device_quiet(dev_priv->gmbus[i]); - ret = device_probe_and_attach(dev_priv->gmbus[i]); - if (ret != 0) { - DRM_ERROR("gmbus port %d attach error %d\n", i, ret); + iic_dev = device_find_child(iic_dev, "iicbus", -1); + if (iic_dev == NULL) { + DRM_ERROR("gmbus bridge doesn't have iicbus child\n"); goto err; } + dev_priv->gmbus[i] = iic_dev; + intel_iic_reset(dev_priv->gmbus[i], 0, 0, NULL); } @@ -683,31 +647,9 @@ static void intel_teardown_gmbus_m(struct drm_device *dev, int m) { struct drm_i915_private *dev_priv; - int i; dev_priv = dev->dev_private; - for (i = m; i>= 0; i--) { - if (dev_priv->gmbus[i] != 0) { - device_delete_child(dev_priv->gmbus_bridge[i], - dev_priv->gmbus[i]); - dev_priv->gmbus[i] = NULL; - } - if (dev_priv->gmbus_bridge[i] != 0) { - device_delete_child(dev->device, - dev_priv->gmbus_bridge[i]); - dev_priv->gmbus_bridge[i] = NULL; - } - if (dev_priv->bbbus[i] != 0) { - device_delete_child(dev_priv->bbbus_bridge[i], - dev_priv->bbbus[i]); - dev_priv->bbbus[i] = NULL; - } - if (dev_priv->bbbus_bridge[i] != 0) { - device_delete_child(dev->device, - dev_priv->bbbus_bridge[i]); - dev_priv->bbbus_bridge[i] = NULL; - } - } + free(dev_priv->gmbus, DRM_MEM_DRIVER); dev_priv->gmbus = NULL; free(dev_priv->bbbus, DRM_MEM_DRIVER);