Merge tag 'tag-chrome-platform-for-v5.4' of git://git.kernel.org/pub/scm/linux/kernel...
[linux-2.6-block.git] / drivers / media / platform / cros-ec-cec / cros-ec-cec.c
index f9fd4bda2a940ca70450c0dd5e3c9ca4ec7bad16..4a3b3810fd895691488e1c97c329944306189669 100644 (file)
@@ -207,10 +207,10 @@ static SIMPLE_DEV_PM_OPS(cros_ec_cec_pm_ops,
  */
 
 struct cec_dmi_match {
-       char *sys_vendor;
-       char *product_name;
-       char *devname;
-       char *conn;
+       const char *sys_vendor;
+       const char *product_name;
+       const char *devname;
+       const char *conn;
 };
 
 static const struct cec_dmi_match cec_dmi_match_table[] = {
@@ -218,8 +218,8 @@ static const struct cec_dmi_match cec_dmi_match_table[] = {
        { "Google", "Fizz", "0000:00:02.0", "Port B" },
 };
 
-static int cros_ec_cec_get_notifier(struct device *dev,
-                                   struct cec_notifier **notify)
+static struct device *cros_ec_cec_find_hdmi_dev(struct device *dev,
+                                               const char **conn)
 {
        int i;
 
@@ -234,26 +234,25 @@ static int cros_ec_cec_get_notifier(struct device *dev,
                        d = bus_find_device_by_name(&pci_bus_type, NULL,
                                                    m->devname);
                        if (!d)
-                               return -EPROBE_DEFER;
-
-                       *notify = cec_notifier_get_conn(d, m->conn);
+                               return ERR_PTR(-EPROBE_DEFER);
                        put_device(d);
-                       return 0;
+                       *conn = m->conn;
+                       return d;
                }
        }
 
        /* Hardware support must be added in the cec_dmi_match_table */
        dev_warn(dev, "CEC notifier not configured for this hardware\n");
 
-       return -ENODEV;
+       return ERR_PTR(-ENODEV);
 }
 
 #else
 
-static int cros_ec_cec_get_notifier(struct device *dev,
-                                   struct cec_notifier **notify)
+static struct device *cros_ec_cec_find_hdmi_dev(struct device *dev,
+                                               const char **conn)
 {
-       return -ENODEV;
+       return ERR_PTR(-ENODEV);
 }
 
 #endif
@@ -263,8 +262,14 @@ static int cros_ec_cec_probe(struct platform_device *pdev)
        struct cros_ec_dev *ec_dev = dev_get_drvdata(pdev->dev.parent);
        struct cros_ec_device *cros_ec = ec_dev->ec_dev;
        struct cros_ec_cec *cros_ec_cec;
+       struct device *hdmi_dev;
+       const char *conn = NULL;
        int ret;
 
+       hdmi_dev = cros_ec_cec_find_hdmi_dev(&pdev->dev, &conn);
+       if (IS_ERR(hdmi_dev))
+               return PTR_ERR(hdmi_dev);
+
        cros_ec_cec = devm_kzalloc(&pdev->dev, sizeof(*cros_ec_cec),
                                   GFP_KERNEL);
        if (!cros_ec_cec)
@@ -273,10 +278,6 @@ static int cros_ec_cec_probe(struct platform_device *pdev)
        platform_set_drvdata(pdev, cros_ec_cec);
        cros_ec_cec->cros_ec = cros_ec;
 
-       ret = cros_ec_cec_get_notifier(&pdev->dev, &cros_ec_cec->notify);
-       if (ret)
-               return ret;
-
        ret = device_init_wakeup(&pdev->dev, 1);
        if (ret) {
                dev_err(&pdev->dev, "failed to initialize wakeup\n");
@@ -284,29 +285,39 @@ static int cros_ec_cec_probe(struct platform_device *pdev)
        }
 
        cros_ec_cec->adap = cec_allocate_adapter(&cros_ec_cec_ops, cros_ec_cec,
-                                                DRV_NAME, CEC_CAP_DEFAULTS, 1);
+                                                DRV_NAME,
+                                                CEC_CAP_DEFAULTS |
+                                                CEC_CAP_CONNECTOR_INFO, 1);
        if (IS_ERR(cros_ec_cec->adap))
                return PTR_ERR(cros_ec_cec->adap);
 
+       cros_ec_cec->notify = cec_notifier_cec_adap_register(hdmi_dev, conn,
+                                                            cros_ec_cec->adap);
+       if (!cros_ec_cec->notify) {
+               ret = -ENOMEM;
+               goto out_probe_adapter;
+       }
+
        /* Get CEC events from the EC. */
        cros_ec_cec->notifier.notifier_call = cros_ec_cec_event;
        ret = blocking_notifier_chain_register(&cros_ec->event_notifier,
                                               &cros_ec_cec->notifier);
        if (ret) {
                dev_err(&pdev->dev, "failed to register notifier\n");
-               cec_delete_adapter(cros_ec_cec->adap);
-               return ret;
+               goto out_probe_notify;
        }
 
        ret = cec_register_adapter(cros_ec_cec->adap, &pdev->dev);
-       if (ret < 0) {
-               cec_delete_adapter(cros_ec_cec->adap);
-               return ret;
-       }
-
-       cec_register_cec_notifier(cros_ec_cec->adap, cros_ec_cec->notify);
+       if (ret < 0)
+               goto out_probe_notify;
 
        return 0;
+
+out_probe_notify:
+       cec_notifier_cec_adap_unregister(cros_ec_cec->notify);
+out_probe_adapter:
+       cec_delete_adapter(cros_ec_cec->adap);
+       return ret;
 }
 
 static int cros_ec_cec_remove(struct platform_device *pdev)
@@ -324,11 +335,9 @@ static int cros_ec_cec_remove(struct platform_device *pdev)
                return ret;
        }
 
+       cec_notifier_cec_adap_unregister(cros_ec_cec->notify);
        cec_unregister_adapter(cros_ec_cec->adap);
 
-       if (cros_ec_cec->notify)
-               cec_notifier_put(cros_ec_cec->notify);
-
        return 0;
 }