diff options
author | Russell King <rmk+kernel@arm.linux.org.uk> | 2014-02-07 14:49:44 -0500 |
---|---|---|
committer | Russell King <rmk+kernel@arm.linux.org.uk> | 2014-08-01 12:16:56 -0400 |
commit | c707c3619ca81f499a5ce032021405e989a96ff0 (patch) | |
tree | aa93acd693f8a9d489bf57d4b23af0012fc8d6c6 /drivers/gpu/drm/i2c | |
parent | a8f4d4d63739e4bca459ff40636f1d9e4b7ef5e6 (diff) |
drm/i2c: tda998x: add component support
Add component helper support to the tda998x driver. This permits the
TDA998x to be declared as a separate device in device tree, and bound
at the appropriate moment with a co-operating card driver.
The existing slave_encoder interfaces are kept while there are existing
users of it in order to prevent regressions.
Tested-by: Darren Etheridge <detheridge@ti.com>
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
Diffstat (limited to 'drivers/gpu/drm/i2c')
-rw-r--r-- | drivers/gpu/drm/i2c/tda998x_drv.c | 212 |
1 files changed, 198 insertions, 14 deletions
diff --git a/drivers/gpu/drm/i2c/tda998x_drv.c b/drivers/gpu/drm/i2c/tda998x_drv.c index 64e120c5299a..3b07ff7e6348 100644 --- a/drivers/gpu/drm/i2c/tda998x_drv.c +++ b/drivers/gpu/drm/i2c/tda998x_drv.c | |||
@@ -15,8 +15,7 @@ | |||
15 | * this program. If not, see <http://www.gnu.org/licenses/>. | 15 | * this program. If not, see <http://www.gnu.org/licenses/>. |
16 | */ | 16 | */ |
17 | 17 | ||
18 | 18 | #include <linux/component.h> | |
19 | |||
20 | #include <linux/hdmi.h> | 19 | #include <linux/hdmi.h> |
21 | #include <linux/module.h> | 20 | #include <linux/module.h> |
22 | #include <linux/irq.h> | 21 | #include <linux/irq.h> |
@@ -1252,18 +1251,6 @@ static struct drm_encoder_slave_funcs tda998x_encoder_slave_funcs = { | |||
1252 | 1251 | ||
1253 | /* I2C driver functions */ | 1252 | /* I2C driver functions */ |
1254 | 1253 | ||
1255 | static int | ||
1256 | tda998x_probe(struct i2c_client *client, const struct i2c_device_id *id) | ||
1257 | { | ||
1258 | return 0; | ||
1259 | } | ||
1260 | |||
1261 | static int | ||
1262 | tda998x_remove(struct i2c_client *client) | ||
1263 | { | ||
1264 | return 0; | ||
1265 | } | ||
1266 | |||
1267 | static int tda998x_create(struct i2c_client *client, struct tda998x_priv *priv) | 1254 | static int tda998x_create(struct i2c_client *client, struct tda998x_priv *priv) |
1268 | { | 1255 | { |
1269 | struct device_node *np = client->dev.of_node; | 1256 | struct device_node *np = client->dev.of_node; |
@@ -1412,6 +1399,203 @@ static int tda998x_encoder_init(struct i2c_client *client, | |||
1412 | return 0; | 1399 | return 0; |
1413 | } | 1400 | } |
1414 | 1401 | ||
1402 | struct tda998x_priv2 { | ||
1403 | struct tda998x_priv base; | ||
1404 | struct drm_encoder encoder; | ||
1405 | struct drm_connector connector; | ||
1406 | }; | ||
1407 | |||
1408 | #define conn_to_tda998x_priv2(x) \ | ||
1409 | container_of(x, struct tda998x_priv2, connector); | ||
1410 | |||
1411 | #define enc_to_tda998x_priv2(x) \ | ||
1412 | container_of(x, struct tda998x_priv2, encoder); | ||
1413 | |||
1414 | static void tda998x_encoder2_dpms(struct drm_encoder *encoder, int mode) | ||
1415 | { | ||
1416 | struct tda998x_priv2 *priv = enc_to_tda998x_priv2(encoder); | ||
1417 | |||
1418 | tda998x_encoder_dpms(&priv->base, mode); | ||
1419 | } | ||
1420 | |||
1421 | static void tda998x_encoder_prepare(struct drm_encoder *encoder) | ||
1422 | { | ||
1423 | tda998x_encoder2_dpms(encoder, DRM_MODE_DPMS_OFF); | ||
1424 | } | ||
1425 | |||
1426 | static void tda998x_encoder_commit(struct drm_encoder *encoder) | ||
1427 | { | ||
1428 | tda998x_encoder2_dpms(encoder, DRM_MODE_DPMS_ON); | ||
1429 | } | ||
1430 | |||
1431 | static void tda998x_encoder2_mode_set(struct drm_encoder *encoder, | ||
1432 | struct drm_display_mode *mode, | ||
1433 | struct drm_display_mode *adjusted_mode) | ||
1434 | { | ||
1435 | struct tda998x_priv2 *priv = enc_to_tda998x_priv2(encoder); | ||
1436 | |||
1437 | tda998x_encoder_mode_set(&priv->base, mode, adjusted_mode); | ||
1438 | } | ||
1439 | |||
1440 | static const struct drm_encoder_helper_funcs tda998x_encoder_helper_funcs = { | ||
1441 | .dpms = tda998x_encoder2_dpms, | ||
1442 | .save = tda998x_encoder_save, | ||
1443 | .restore = tda998x_encoder_restore, | ||
1444 | .mode_fixup = tda998x_encoder_mode_fixup, | ||
1445 | .prepare = tda998x_encoder_prepare, | ||
1446 | .commit = tda998x_encoder_commit, | ||
1447 | .mode_set = tda998x_encoder2_mode_set, | ||
1448 | }; | ||
1449 | |||
1450 | static void tda998x_encoder_destroy(struct drm_encoder *encoder) | ||
1451 | { | ||
1452 | struct tda998x_priv2 *priv = enc_to_tda998x_priv2(encoder); | ||
1453 | |||
1454 | tda998x_destroy(&priv->base); | ||
1455 | drm_encoder_cleanup(encoder); | ||
1456 | } | ||
1457 | |||
1458 | static const struct drm_encoder_funcs tda998x_encoder_funcs = { | ||
1459 | .destroy = tda998x_encoder_destroy, | ||
1460 | }; | ||
1461 | |||
1462 | static int tda998x_connector_get_modes(struct drm_connector *connector) | ||
1463 | { | ||
1464 | struct tda998x_priv2 *priv = conn_to_tda998x_priv2(connector); | ||
1465 | |||
1466 | return tda998x_encoder_get_modes(&priv->base, connector); | ||
1467 | } | ||
1468 | |||
1469 | static int tda998x_connector_mode_valid(struct drm_connector *connector, | ||
1470 | struct drm_display_mode *mode) | ||
1471 | { | ||
1472 | struct tda998x_priv2 *priv = conn_to_tda998x_priv2(connector); | ||
1473 | |||
1474 | return tda998x_encoder_mode_valid(&priv->base, mode); | ||
1475 | } | ||
1476 | |||
1477 | static struct drm_encoder * | ||
1478 | tda998x_connector_best_encoder(struct drm_connector *connector) | ||
1479 | { | ||
1480 | struct tda998x_priv2 *priv = conn_to_tda998x_priv2(connector); | ||
1481 | |||
1482 | return &priv->encoder; | ||
1483 | } | ||
1484 | |||
1485 | static | ||
1486 | const struct drm_connector_helper_funcs tda998x_connector_helper_funcs = { | ||
1487 | .get_modes = tda998x_connector_get_modes, | ||
1488 | .mode_valid = tda998x_connector_mode_valid, | ||
1489 | .best_encoder = tda998x_connector_best_encoder, | ||
1490 | }; | ||
1491 | |||
1492 | static enum drm_connector_status | ||
1493 | tda998x_connector_detect(struct drm_connector *connector, bool force) | ||
1494 | { | ||
1495 | struct tda998x_priv2 *priv = conn_to_tda998x_priv2(connector); | ||
1496 | |||
1497 | return tda998x_encoder_detect(&priv->base); | ||
1498 | } | ||
1499 | |||
1500 | static void tda998x_connector_destroy(struct drm_connector *connector) | ||
1501 | { | ||
1502 | drm_sysfs_connector_remove(connector); | ||
1503 | drm_connector_cleanup(connector); | ||
1504 | } | ||
1505 | |||
1506 | static const struct drm_connector_funcs tda998x_connector_funcs = { | ||
1507 | .dpms = drm_helper_connector_dpms, | ||
1508 | .fill_modes = drm_helper_probe_single_connector_modes, | ||
1509 | .detect = tda998x_connector_detect, | ||
1510 | .destroy = tda998x_connector_destroy, | ||
1511 | }; | ||
1512 | |||
1513 | static int tda998x_bind(struct device *dev, struct device *master, void *data) | ||
1514 | { | ||
1515 | struct tda998x_encoder_params *params = dev->platform_data; | ||
1516 | struct i2c_client *client = to_i2c_client(dev); | ||
1517 | struct drm_device *drm = data; | ||
1518 | struct tda998x_priv2 *priv; | ||
1519 | int ret; | ||
1520 | |||
1521 | priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); | ||
1522 | if (!priv) | ||
1523 | return -ENOMEM; | ||
1524 | |||
1525 | dev_set_drvdata(dev, priv); | ||
1526 | |||
1527 | priv->base.encoder = &priv->encoder; | ||
1528 | priv->connector.interlace_allowed = 1; | ||
1529 | priv->encoder.possible_crtcs = 1 << 0; | ||
1530 | |||
1531 | ret = tda998x_create(client, &priv->base); | ||
1532 | if (ret) | ||
1533 | return ret; | ||
1534 | |||
1535 | if (!dev->of_node && params) | ||
1536 | tda998x_encoder_set_config(&priv->base, params); | ||
1537 | |||
1538 | tda998x_encoder_set_polling(&priv->base, &priv->connector); | ||
1539 | |||
1540 | drm_encoder_helper_add(&priv->encoder, &tda998x_encoder_helper_funcs); | ||
1541 | ret = drm_encoder_init(drm, &priv->encoder, &tda998x_encoder_funcs, | ||
1542 | DRM_MODE_ENCODER_TMDS); | ||
1543 | if (ret) | ||
1544 | goto err_encoder; | ||
1545 | |||
1546 | drm_connector_helper_add(&priv->connector, | ||
1547 | &tda998x_connector_helper_funcs); | ||
1548 | ret = drm_connector_init(drm, &priv->connector, | ||
1549 | &tda998x_connector_funcs, | ||
1550 | DRM_MODE_CONNECTOR_HDMIA); | ||
1551 | if (ret) | ||
1552 | goto err_connector; | ||
1553 | |||
1554 | ret = drm_sysfs_connector_add(&priv->connector); | ||
1555 | if (ret) | ||
1556 | goto err_sysfs; | ||
1557 | |||
1558 | priv->connector.encoder = &priv->encoder; | ||
1559 | drm_mode_connector_attach_encoder(&priv->connector, &priv->encoder); | ||
1560 | |||
1561 | return 0; | ||
1562 | |||
1563 | err_sysfs: | ||
1564 | drm_connector_cleanup(&priv->connector); | ||
1565 | err_connector: | ||
1566 | drm_encoder_cleanup(&priv->encoder); | ||
1567 | err_encoder: | ||
1568 | tda998x_destroy(&priv->base); | ||
1569 | return ret; | ||
1570 | } | ||
1571 | |||
1572 | static void tda998x_unbind(struct device *dev, struct device *master, | ||
1573 | void *data) | ||
1574 | { | ||
1575 | struct tda998x_priv2 *priv = dev_get_drvdata(dev); | ||
1576 | |||
1577 | drm_connector_cleanup(&priv->connector); | ||
1578 | drm_encoder_cleanup(&priv->encoder); | ||
1579 | tda998x_destroy(&priv->base); | ||
1580 | } | ||
1581 | |||
1582 | static const struct component_ops tda998x_ops = { | ||
1583 | .bind = tda998x_bind, | ||
1584 | .unbind = tda998x_unbind, | ||
1585 | }; | ||
1586 | |||
1587 | static int | ||
1588 | tda998x_probe(struct i2c_client *client, const struct i2c_device_id *id) | ||
1589 | { | ||
1590 | return component_add(&client->dev, &tda998x_ops); | ||
1591 | } | ||
1592 | |||
1593 | static int tda998x_remove(struct i2c_client *client) | ||
1594 | { | ||
1595 | component_del(&client->dev, &tda998x_ops); | ||
1596 | return 0; | ||
1597 | } | ||
1598 | |||
1415 | #ifdef CONFIG_OF | 1599 | #ifdef CONFIG_OF |
1416 | static const struct of_device_id tda998x_dt_ids[] = { | 1600 | static const struct of_device_id tda998x_dt_ids[] = { |
1417 | { .compatible = "nxp,tda998x", }, | 1601 | { .compatible = "nxp,tda998x", }, |