Thread (13 messages) 13 messages, 3 authors, 2017-06-20

Re: [PATCH v3 2/4] [media] platform: Add Synopsys Designware HDMI RX Controller Driver

From: Sylwester Nawrocki <hidden>
Date: 2017-06-19 22:10:19
Also in: linux-media, lkml

On 06/19/2017 11:33 AM, Jose Abreu wrote:
On 18-06-2017 19:04, Sylwester Nawrocki wrote:
quoted
On 06/16/2017 06:38 PM, Jose Abreu wrote:
quoted
This is an initial submission for the Synopsys Designware HDMI RX
Controller Driver. This driver interacts with a phy driver so that
a communication between them is created and a video pipeline is
configured.

The controller + phy pipeline can then be integrated into a fully
featured system that can be able to receive video up to 4k@60Hz
with deep color 48bit RGB, depending on the platform. Although,
this initial version does not yet handle deep color modes.
Signed-off-by: Jose Abreu <joabreu-HKixBCOQz3hWk0Htik3J/w@public.gmane.org>

+static int dw_hdmi_phy_init(struct dw_hdmi_dev *dw_dev)
+{
quoted
quoted
+	request_module(pdevinfo.name);
+
+	dw_dev->phy_pdev = platform_device_register_full(&pdevinfo);
+	if (IS_ERR(dw_dev->phy_pdev)) {
+		dev_err(dw_dev->dev, "failed to register phy device\n");
+		return PTR_ERR(dw_dev->phy_pdev);
+	}
+
+	if (!dw_dev->phy_pdev->dev.driver) {
+		dev_err(dw_dev->dev, "failed to initialize phy driver\n");
+		goto err;
+	}
I think this is not safe because there is nothing preventing unbinding
or unloading the driver at this point.
quoted
+	if (!try_module_get(dw_dev->phy_pdev->dev.driver->owner)) {
So dw_dev->phy_pdev->dev.driver may be already NULL here.
How can I make sure it wont be NULL? Because I've seen other
media drivers do this and I don't think they do any kind of
locking, but they do this mainly for I2C subdevs.
You could do device_lock(dev)/device_unlock(dev) to avoid possible races. 
And setting 'suppress_bind_attrs' field in the sub-device drivers would 
disable sysfs unbind attributes, so sub-device driver wouldn't get unbound
unexpectedly trough sysfs.
 
quoted
quoted
+		dev_err(dw_dev->dev, "failed to get phy module\n");
+		goto err;
+	}
+
+	dw_dev->phy_sd = dev_get_drvdata(&dw_dev->phy_pdev->dev);
+	if (!dw_dev->phy_sd) {
+		dev_err(dw_dev->dev, "failed to get phy subdev\n");
+		goto err_put;
+	}
+
+	if (v4l2_device_register_subdev(&dw_dev->v4l2_dev, dw_dev->phy_sd)) {
+		dev_err(dw_dev->dev, "failed to register phy subdev\n");
+		goto err_put;
+	}
I'd suggest usign v4l2-async API, so we use a common pattern for sub-device
registration.  And with recent change [1] you could handle this PHY subdev
in a standard way.  That might be more complicated than it is now but should
make any future platform integration easier.
So I will instantiate phy driver and then wait for phy driver to
register into v4l2 core?
Yes, for instance the RX controller driver registers a notifier, instantiates
the child PHY device and then waits until the PHY driver completes initialization.
quoted
quoted
+	module_put(dw_dev->phy_pdev->dev.driver->owner);
+	return 0;
+
+err_put:
+	module_put(dw_dev->phy_pdev->dev.driver->owner);
+err:
+	platform_device_unregister(dw_dev->phy_pdev);
+	return -EINVAL;
+}
quoted
quoted
+static int dw_hdmi_power_on(struct dw_hdmi_dev *dw_dev, u32 input)
+{
+	struct dw_hdmi_work_data *data;
+	unsigned long flags;
+
+	data = devm_kzalloc(dw_dev->dev, sizeof(*data), GFP_KERNEL);
Why use devm_{kzalloc, kfree} when dw_hdmi_power_on() is not only called
in the device's probe() callback, but in other places, including interrupt
handler?  devm_* API is normally used when life time of a resource is more
or less equal to life time of struct device or its matched driver.  Were
there any specific reasons to not just use kzalloc()/kfree() ?
No specific reason, I just thought it would be safer because if I
cancel a work before it started then memory will remain
allocated. But I will change to kzalloc().
OK, I overlooked such situation. Since you allow one job queued maybe
just embed struct work_struct in struct dw_hdmi_dev and retrieve it with
container_of() macro in the work handler and use additional field in
struct dw_hdmi_dev protected with dw_dev->lock for passing the input 
index?
quoted
quoted
+	if (!data)
+		return -ENOMEM;
+
+	INIT_WORK(&data->work, dw_hdmi_work_handler);
+	data->dw_dev = dw_dev;
+	data->input = input;
+
+	spin_lock_irqsave(&dw_dev->lock, flags);
+	if (dw_dev->pending_config) {
+		devm_kfree(dw_dev->dev, data);
+		spin_unlock_irqrestore(&dw_dev->lock, flags);
+		return 0;
+	}
+
+	queue_work(dw_dev->wq, &data->work);
+	dw_dev->pending_config = true;
+	spin_unlock_irqrestore(&dw_dev->lock, flags);
+	return 0;
+}
quoted
quoted
+struct dw_hdmi_rx_pdata {
+	/* Controller configuration */
quoted
quoted
+	struct dw_hdmi_hdcp14_key hdcp14_keys;
+	/* 5V sense interface */
+	bool (*dw_5v_status)(void __iomem *regs, int input);
+	void (*dw_5v_clear)(void __iomem *regs);
+	void __iomem *dw_5v_arg;> +	/* Zcal interface */
+	void (*dw_zcal_reset)(void __iomem *regs);
+	bool (*dw_zcal_done)(void __iomem *regs);
+	void __iomem *dw_zcal_arg;
I'm just wondering if these operations could be modeled with the regmap,
so we could avoid callbacks in the platform data structure.
Hmm, I don't think that is safe because registers may not be
adjacent to each other. And maybe I was a little generous in
passing a __iomem argument, maybe it should be just void instead
because this can be not a regmap at all.
I meant two separate regmaps, but it's not that good anyway, since
register address and register bit fields not specific to the HDMI RX
block would need to be handled in this driver.

--
Regards,
Sylwester 
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help