Jean-Francois Moine
2014-01-30 18:00:11 UTC
On Thu, 30 Jan 2014 14:20:56 +0200
- in the DT, define the tda998x in a i2c subnode:
&i2c0 {
tda998x: hdmi-encoder {
compatible =3D "nxp,tda998x";
reg =3D <0x70>;
/* the video ports are OK by default */
/* define the interrupt if you want to use it */
};
};
- in tilcdc_slave.c, in the function slave_encoder_create(), instead of
using drm_i2c_encoder_init(), do quite the same, but without calling
request_module() nor i2c_new_device().
This can be done as follows (the code is not compiled):
--------------------8<---------------------
static struct drm_encoder *slave_encoder_create(struct drm_device *dev,
struct slave_module *mod)
{
struct slave_encoder *slave_encoder;
struct drm_encoder *encoder;
int ret;
/* ------ added ------ */
struct device_node *np;
static const struct of_device_id tda_dt[] =3D {
{ .compatible =3D "nxp,tda998x" },
{ },
};
/* ------ end added ------ */
... no change ...
drm_encoder_helper_add(encoder, &slave_encoder_helper_funcs);
/* ------ added ------ */
/* search the tda998x device */
np =3D of_find_matching_node_and_match(NULL, tda_dt, NULL);
if (np && of_device_is_available(np)) {
struct i2c_client *i2c_client;
struct drm_i2c_encoder_driver *encoder_drv;
struct module *module;
/* the tda998x is in the DT */
i2c_client =3D of_find_i2c_device_by_node(np);
of_node_put(np);
if (!i2c_client) {
dev_err(dev->dev, "no tda998x i2c client\n");
goto fail;
}
to_encoder_slave(encoder)->bus_priv =3D i2c_client;
encoder_drv =3D to_drm_i2c_encoder_driver(
to_i2c_driver(i2c_client->dev.driver));
/* lock the tda998x module in memory */
module =3D to_i2c_driver(i2c_client->dev.driver)->driver.owner;
if (!module || !try_module_get(module)) {
dev_err(dev->dev, "cannot get module %s\n", module->name);
goto fail;
}
ret =3D encoder_drv->encoder_init(i2c_client, dev, encoder_slave);
if (ret < 0) {
dev_err(dev->dev, "slave encoder init failed\n");
module_put(module);
goto fail;
}
/* set_config is useless */
return encoder;
}
/* ------ end added ------ */
ret =3D drm_i2c_encoder_init(dev, to_encoder_slave(encoder), mod->i2c,=
&info);
if (ret)
goto fail;
return encoder;
fail:
slave_encoder_destroy(encoder);
return NULL;
}
--------------------8<---------------------
When the tda998x is in the DT, the i2c_client is already created.
It must not be freed, and so, the function drm_i2c_encoder_destroy()
must not be called. But, the module must be explicitly unlocked in
slave_encoder_destroy(), and then, there must be some flag in the
structures for this job to be done...
--=20
Ken ar c'henta=C3=B1 | ** Breizh ha Linux atav! **
Jef | http://moinejf.free.fr/
--
To unsubscribe from this list: send the line "unsubscribe linux-omap" i=
n
the body of a message to ***@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
I am having trouble getting the tda998x-codec working on BBB. The=20
problem is I do not have a DT node for the tda998x driver. Instead I=20
have tilcdc-slave node that provides pdata for the tda-driver.
=20
I am thinking of solving the problem by adding a reference to the=20
i2c-adapter hosting tda998x as an optional DT property to the codec=20
node. I could then dig the driver instance from the i2c adapter's=20
children. Any better ideas?
I better think about a 'normal' DT definition:problem is I do not have a DT node for the tda998x driver. Instead I=20
have tilcdc-slave node that provides pdata for the tda-driver.
=20
I am thinking of solving the problem by adding a reference to the=20
i2c-adapter hosting tda998x as an optional DT property to the codec=20
node. I could then dig the driver instance from the i2c adapter's=20
children. Any better ideas?
- in the DT, define the tda998x in a i2c subnode:
&i2c0 {
tda998x: hdmi-encoder {
compatible =3D "nxp,tda998x";
reg =3D <0x70>;
/* the video ports are OK by default */
/* define the interrupt if you want to use it */
};
};
- in tilcdc_slave.c, in the function slave_encoder_create(), instead of
using drm_i2c_encoder_init(), do quite the same, but without calling
request_module() nor i2c_new_device().
This can be done as follows (the code is not compiled):
--------------------8<---------------------
static struct drm_encoder *slave_encoder_create(struct drm_device *dev,
struct slave_module *mod)
{
struct slave_encoder *slave_encoder;
struct drm_encoder *encoder;
int ret;
/* ------ added ------ */
struct device_node *np;
static const struct of_device_id tda_dt[] =3D {
{ .compatible =3D "nxp,tda998x" },
{ },
};
/* ------ end added ------ */
... no change ...
drm_encoder_helper_add(encoder, &slave_encoder_helper_funcs);
/* ------ added ------ */
/* search the tda998x device */
np =3D of_find_matching_node_and_match(NULL, tda_dt, NULL);
if (np && of_device_is_available(np)) {
struct i2c_client *i2c_client;
struct drm_i2c_encoder_driver *encoder_drv;
struct module *module;
/* the tda998x is in the DT */
i2c_client =3D of_find_i2c_device_by_node(np);
of_node_put(np);
if (!i2c_client) {
dev_err(dev->dev, "no tda998x i2c client\n");
goto fail;
}
to_encoder_slave(encoder)->bus_priv =3D i2c_client;
encoder_drv =3D to_drm_i2c_encoder_driver(
to_i2c_driver(i2c_client->dev.driver));
/* lock the tda998x module in memory */
module =3D to_i2c_driver(i2c_client->dev.driver)->driver.owner;
if (!module || !try_module_get(module)) {
dev_err(dev->dev, "cannot get module %s\n", module->name);
goto fail;
}
ret =3D encoder_drv->encoder_init(i2c_client, dev, encoder_slave);
if (ret < 0) {
dev_err(dev->dev, "slave encoder init failed\n");
module_put(module);
goto fail;
}
/* set_config is useless */
return encoder;
}
/* ------ end added ------ */
ret =3D drm_i2c_encoder_init(dev, to_encoder_slave(encoder), mod->i2c,=
&info);
if (ret)
goto fail;
return encoder;
fail:
slave_encoder_destroy(encoder);
return NULL;
}
--------------------8<---------------------
When the tda998x is in the DT, the i2c_client is already created.
It must not be freed, and so, the function drm_i2c_encoder_destroy()
must not be called. But, the module must be explicitly unlocked in
slave_encoder_destroy(), and then, there must be some flag in the
structures for this job to be done...
--=20
Ken ar c'henta=C3=B1 | ** Breizh ha Linux atav! **
Jef | http://moinejf.free.fr/
--
To unsubscribe from this list: send the line "unsubscribe linux-omap" i=
n
the body of a message to ***@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html