15f60ed0dSThierry Reding /* 25f60ed0dSThierry Reding * Copyright (C) 2013 Avionic Design GmbH 35f60ed0dSThierry Reding * Copyright (C) 2013 NVIDIA Corporation 45f60ed0dSThierry Reding * 55f60ed0dSThierry Reding * This program is free software; you can redistribute it and/or modify 65f60ed0dSThierry Reding * it under the terms of the GNU General Public License version 2 as 75f60ed0dSThierry Reding * published by the Free Software Foundation. 85f60ed0dSThierry Reding */ 95f60ed0dSThierry Reding 105f60ed0dSThierry Reding #include <linux/clk.h> 115f60ed0dSThierry Reding #include <linux/host1x.h> 125f60ed0dSThierry Reding #include <linux/module.h> 135f60ed0dSThierry Reding #include <linux/platform_device.h> 145f60ed0dSThierry Reding #include <linux/tegra-powergate.h> 155f60ed0dSThierry Reding 165f60ed0dSThierry Reding #include "drm.h" 175f60ed0dSThierry Reding #include "gem.h" 185f60ed0dSThierry Reding #include "gr3d.h" 195f60ed0dSThierry Reding 205f60ed0dSThierry Reding struct gr3d { 215f60ed0dSThierry Reding struct tegra_drm_client client; 225f60ed0dSThierry Reding struct host1x_channel *channel; 235f60ed0dSThierry Reding struct clk *clk_secondary; 245f60ed0dSThierry Reding struct clk *clk; 255f60ed0dSThierry Reding 265f60ed0dSThierry Reding DECLARE_BITMAP(addr_regs, GR3D_NUM_REGS); 275f60ed0dSThierry Reding }; 285f60ed0dSThierry Reding 295f60ed0dSThierry Reding static inline struct gr3d *to_gr3d(struct tegra_drm_client *client) 305f60ed0dSThierry Reding { 315f60ed0dSThierry Reding return container_of(client, struct gr3d, client); 325f60ed0dSThierry Reding } 335f60ed0dSThierry Reding 345f60ed0dSThierry Reding static int gr3d_init(struct host1x_client *client) 355f60ed0dSThierry Reding { 365f60ed0dSThierry Reding struct tegra_drm_client *drm = host1x_to_drm_client(client); 375f60ed0dSThierry Reding struct tegra_drm *tegra = dev_get_drvdata(client->parent); 385f60ed0dSThierry Reding struct gr3d *gr3d = to_gr3d(drm); 395f60ed0dSThierry Reding 405f60ed0dSThierry Reding gr3d->channel = host1x_channel_request(client->dev); 415f60ed0dSThierry Reding if (!gr3d->channel) 425f60ed0dSThierry Reding return -ENOMEM; 435f60ed0dSThierry Reding 445f60ed0dSThierry Reding client->syncpts[0] = host1x_syncpt_request(client->dev, 0); 455f60ed0dSThierry Reding if (!client->syncpts[0]) { 465f60ed0dSThierry Reding host1x_channel_free(gr3d->channel); 475f60ed0dSThierry Reding return -ENOMEM; 485f60ed0dSThierry Reding } 495f60ed0dSThierry Reding 505f60ed0dSThierry Reding return tegra_drm_register_client(tegra, drm); 515f60ed0dSThierry Reding } 525f60ed0dSThierry Reding 535f60ed0dSThierry Reding static int gr3d_exit(struct host1x_client *client) 545f60ed0dSThierry Reding { 555f60ed0dSThierry Reding struct tegra_drm_client *drm = host1x_to_drm_client(client); 565f60ed0dSThierry Reding struct tegra_drm *tegra = dev_get_drvdata(client->parent); 575f60ed0dSThierry Reding struct gr3d *gr3d = to_gr3d(drm); 585f60ed0dSThierry Reding int err; 595f60ed0dSThierry Reding 605f60ed0dSThierry Reding err = tegra_drm_unregister_client(tegra, drm); 615f60ed0dSThierry Reding if (err < 0) 625f60ed0dSThierry Reding return err; 635f60ed0dSThierry Reding 645f60ed0dSThierry Reding host1x_syncpt_free(client->syncpts[0]); 655f60ed0dSThierry Reding host1x_channel_free(gr3d->channel); 665f60ed0dSThierry Reding 675f60ed0dSThierry Reding return 0; 685f60ed0dSThierry Reding } 695f60ed0dSThierry Reding 705f60ed0dSThierry Reding static const struct host1x_client_ops gr3d_client_ops = { 715f60ed0dSThierry Reding .init = gr3d_init, 725f60ed0dSThierry Reding .exit = gr3d_exit, 735f60ed0dSThierry Reding }; 745f60ed0dSThierry Reding 755f60ed0dSThierry Reding static int gr3d_open_channel(struct tegra_drm_client *client, 765f60ed0dSThierry Reding struct tegra_drm_context *context) 775f60ed0dSThierry Reding { 785f60ed0dSThierry Reding struct gr3d *gr3d = to_gr3d(client); 795f60ed0dSThierry Reding 805f60ed0dSThierry Reding context->channel = host1x_channel_get(gr3d->channel); 815f60ed0dSThierry Reding if (!context->channel) 825f60ed0dSThierry Reding return -ENOMEM; 835f60ed0dSThierry Reding 845f60ed0dSThierry Reding return 0; 855f60ed0dSThierry Reding } 865f60ed0dSThierry Reding 875f60ed0dSThierry Reding static void gr3d_close_channel(struct tegra_drm_context *context) 885f60ed0dSThierry Reding { 895f60ed0dSThierry Reding host1x_channel_put(context->channel); 905f60ed0dSThierry Reding } 915f60ed0dSThierry Reding 925f60ed0dSThierry Reding static int gr3d_is_addr_reg(struct device *dev, u32 class, u32 offset) 935f60ed0dSThierry Reding { 945f60ed0dSThierry Reding struct gr3d *gr3d = dev_get_drvdata(dev); 955f60ed0dSThierry Reding 965f60ed0dSThierry Reding switch (class) { 975f60ed0dSThierry Reding case HOST1X_CLASS_HOST1X: 985f60ed0dSThierry Reding if (offset == 0x2b) 995f60ed0dSThierry Reding return 1; 1005f60ed0dSThierry Reding 1015f60ed0dSThierry Reding break; 1025f60ed0dSThierry Reding 1035f60ed0dSThierry Reding case HOST1X_CLASS_GR3D: 1045f60ed0dSThierry Reding if (offset >= GR3D_NUM_REGS) 1055f60ed0dSThierry Reding break; 1065f60ed0dSThierry Reding 1075f60ed0dSThierry Reding if (test_bit(offset, gr3d->addr_regs)) 1085f60ed0dSThierry Reding return 1; 1095f60ed0dSThierry Reding 1105f60ed0dSThierry Reding break; 1115f60ed0dSThierry Reding } 1125f60ed0dSThierry Reding 1135f60ed0dSThierry Reding return 0; 1145f60ed0dSThierry Reding } 1155f60ed0dSThierry Reding 1165f60ed0dSThierry Reding static const struct tegra_drm_client_ops gr3d_ops = { 1175f60ed0dSThierry Reding .open_channel = gr3d_open_channel, 1185f60ed0dSThierry Reding .close_channel = gr3d_close_channel, 1195f60ed0dSThierry Reding .is_addr_reg = gr3d_is_addr_reg, 1205f60ed0dSThierry Reding .submit = tegra_drm_submit, 1215f60ed0dSThierry Reding }; 1225f60ed0dSThierry Reding 1235f60ed0dSThierry Reding static const struct of_device_id tegra_gr3d_match[] = { 1245f60ed0dSThierry Reding { .compatible = "nvidia,tegra114-gr3d" }, 1255f60ed0dSThierry Reding { .compatible = "nvidia,tegra30-gr3d" }, 1265f60ed0dSThierry Reding { .compatible = "nvidia,tegra20-gr3d" }, 1275f60ed0dSThierry Reding { } 1285f60ed0dSThierry Reding }; 1295f60ed0dSThierry Reding 1305f60ed0dSThierry Reding static const u32 gr3d_addr_regs[] = { 1315f60ed0dSThierry Reding GR3D_IDX_ATTRIBUTE( 0), 1325f60ed0dSThierry Reding GR3D_IDX_ATTRIBUTE( 1), 1335f60ed0dSThierry Reding GR3D_IDX_ATTRIBUTE( 2), 1345f60ed0dSThierry Reding GR3D_IDX_ATTRIBUTE( 3), 1355f60ed0dSThierry Reding GR3D_IDX_ATTRIBUTE( 4), 1365f60ed0dSThierry Reding GR3D_IDX_ATTRIBUTE( 5), 1375f60ed0dSThierry Reding GR3D_IDX_ATTRIBUTE( 6), 1385f60ed0dSThierry Reding GR3D_IDX_ATTRIBUTE( 7), 1395f60ed0dSThierry Reding GR3D_IDX_ATTRIBUTE( 8), 1405f60ed0dSThierry Reding GR3D_IDX_ATTRIBUTE( 9), 1415f60ed0dSThierry Reding GR3D_IDX_ATTRIBUTE(10), 1425f60ed0dSThierry Reding GR3D_IDX_ATTRIBUTE(11), 1435f60ed0dSThierry Reding GR3D_IDX_ATTRIBUTE(12), 1445f60ed0dSThierry Reding GR3D_IDX_ATTRIBUTE(13), 1455f60ed0dSThierry Reding GR3D_IDX_ATTRIBUTE(14), 1465f60ed0dSThierry Reding GR3D_IDX_ATTRIBUTE(15), 1475f60ed0dSThierry Reding GR3D_IDX_INDEX_BASE, 1485f60ed0dSThierry Reding GR3D_QR_ZTAG_ADDR, 1495f60ed0dSThierry Reding GR3D_QR_CTAG_ADDR, 1505f60ed0dSThierry Reding GR3D_QR_CZ_ADDR, 1515f60ed0dSThierry Reding GR3D_TEX_TEX_ADDR( 0), 1525f60ed0dSThierry Reding GR3D_TEX_TEX_ADDR( 1), 1535f60ed0dSThierry Reding GR3D_TEX_TEX_ADDR( 2), 1545f60ed0dSThierry Reding GR3D_TEX_TEX_ADDR( 3), 1555f60ed0dSThierry Reding GR3D_TEX_TEX_ADDR( 4), 1565f60ed0dSThierry Reding GR3D_TEX_TEX_ADDR( 5), 1575f60ed0dSThierry Reding GR3D_TEX_TEX_ADDR( 6), 1585f60ed0dSThierry Reding GR3D_TEX_TEX_ADDR( 7), 1595f60ed0dSThierry Reding GR3D_TEX_TEX_ADDR( 8), 1605f60ed0dSThierry Reding GR3D_TEX_TEX_ADDR( 9), 1615f60ed0dSThierry Reding GR3D_TEX_TEX_ADDR(10), 1625f60ed0dSThierry Reding GR3D_TEX_TEX_ADDR(11), 1635f60ed0dSThierry Reding GR3D_TEX_TEX_ADDR(12), 1645f60ed0dSThierry Reding GR3D_TEX_TEX_ADDR(13), 1655f60ed0dSThierry Reding GR3D_TEX_TEX_ADDR(14), 1665f60ed0dSThierry Reding GR3D_TEX_TEX_ADDR(15), 1675f60ed0dSThierry Reding GR3D_DW_MEMORY_OUTPUT_ADDRESS, 1685f60ed0dSThierry Reding GR3D_GLOBAL_SURFADDR( 0), 1695f60ed0dSThierry Reding GR3D_GLOBAL_SURFADDR( 1), 1705f60ed0dSThierry Reding GR3D_GLOBAL_SURFADDR( 2), 1715f60ed0dSThierry Reding GR3D_GLOBAL_SURFADDR( 3), 1725f60ed0dSThierry Reding GR3D_GLOBAL_SURFADDR( 4), 1735f60ed0dSThierry Reding GR3D_GLOBAL_SURFADDR( 5), 1745f60ed0dSThierry Reding GR3D_GLOBAL_SURFADDR( 6), 1755f60ed0dSThierry Reding GR3D_GLOBAL_SURFADDR( 7), 1765f60ed0dSThierry Reding GR3D_GLOBAL_SURFADDR( 8), 1775f60ed0dSThierry Reding GR3D_GLOBAL_SURFADDR( 9), 1785f60ed0dSThierry Reding GR3D_GLOBAL_SURFADDR(10), 1795f60ed0dSThierry Reding GR3D_GLOBAL_SURFADDR(11), 1805f60ed0dSThierry Reding GR3D_GLOBAL_SURFADDR(12), 1815f60ed0dSThierry Reding GR3D_GLOBAL_SURFADDR(13), 1825f60ed0dSThierry Reding GR3D_GLOBAL_SURFADDR(14), 1835f60ed0dSThierry Reding GR3D_GLOBAL_SURFADDR(15), 1845f60ed0dSThierry Reding GR3D_GLOBAL_SPILLSURFADDR, 1855f60ed0dSThierry Reding GR3D_GLOBAL_SURFOVERADDR( 0), 1865f60ed0dSThierry Reding GR3D_GLOBAL_SURFOVERADDR( 1), 1875f60ed0dSThierry Reding GR3D_GLOBAL_SURFOVERADDR( 2), 1885f60ed0dSThierry Reding GR3D_GLOBAL_SURFOVERADDR( 3), 1895f60ed0dSThierry Reding GR3D_GLOBAL_SURFOVERADDR( 4), 1905f60ed0dSThierry Reding GR3D_GLOBAL_SURFOVERADDR( 5), 1915f60ed0dSThierry Reding GR3D_GLOBAL_SURFOVERADDR( 6), 1925f60ed0dSThierry Reding GR3D_GLOBAL_SURFOVERADDR( 7), 1935f60ed0dSThierry Reding GR3D_GLOBAL_SURFOVERADDR( 8), 1945f60ed0dSThierry Reding GR3D_GLOBAL_SURFOVERADDR( 9), 1955f60ed0dSThierry Reding GR3D_GLOBAL_SURFOVERADDR(10), 1965f60ed0dSThierry Reding GR3D_GLOBAL_SURFOVERADDR(11), 1975f60ed0dSThierry Reding GR3D_GLOBAL_SURFOVERADDR(12), 1985f60ed0dSThierry Reding GR3D_GLOBAL_SURFOVERADDR(13), 1995f60ed0dSThierry Reding GR3D_GLOBAL_SURFOVERADDR(14), 2005f60ed0dSThierry Reding GR3D_GLOBAL_SURFOVERADDR(15), 2015f60ed0dSThierry Reding GR3D_GLOBAL_SAMP01SURFADDR( 0), 2025f60ed0dSThierry Reding GR3D_GLOBAL_SAMP01SURFADDR( 1), 2035f60ed0dSThierry Reding GR3D_GLOBAL_SAMP01SURFADDR( 2), 2045f60ed0dSThierry Reding GR3D_GLOBAL_SAMP01SURFADDR( 3), 2055f60ed0dSThierry Reding GR3D_GLOBAL_SAMP01SURFADDR( 4), 2065f60ed0dSThierry Reding GR3D_GLOBAL_SAMP01SURFADDR( 5), 2075f60ed0dSThierry Reding GR3D_GLOBAL_SAMP01SURFADDR( 6), 2085f60ed0dSThierry Reding GR3D_GLOBAL_SAMP01SURFADDR( 7), 2095f60ed0dSThierry Reding GR3D_GLOBAL_SAMP01SURFADDR( 8), 2105f60ed0dSThierry Reding GR3D_GLOBAL_SAMP01SURFADDR( 9), 2115f60ed0dSThierry Reding GR3D_GLOBAL_SAMP01SURFADDR(10), 2125f60ed0dSThierry Reding GR3D_GLOBAL_SAMP01SURFADDR(11), 2135f60ed0dSThierry Reding GR3D_GLOBAL_SAMP01SURFADDR(12), 2145f60ed0dSThierry Reding GR3D_GLOBAL_SAMP01SURFADDR(13), 2155f60ed0dSThierry Reding GR3D_GLOBAL_SAMP01SURFADDR(14), 2165f60ed0dSThierry Reding GR3D_GLOBAL_SAMP01SURFADDR(15), 2175f60ed0dSThierry Reding GR3D_GLOBAL_SAMP23SURFADDR( 0), 2185f60ed0dSThierry Reding GR3D_GLOBAL_SAMP23SURFADDR( 1), 2195f60ed0dSThierry Reding GR3D_GLOBAL_SAMP23SURFADDR( 2), 2205f60ed0dSThierry Reding GR3D_GLOBAL_SAMP23SURFADDR( 3), 2215f60ed0dSThierry Reding GR3D_GLOBAL_SAMP23SURFADDR( 4), 2225f60ed0dSThierry Reding GR3D_GLOBAL_SAMP23SURFADDR( 5), 2235f60ed0dSThierry Reding GR3D_GLOBAL_SAMP23SURFADDR( 6), 2245f60ed0dSThierry Reding GR3D_GLOBAL_SAMP23SURFADDR( 7), 2255f60ed0dSThierry Reding GR3D_GLOBAL_SAMP23SURFADDR( 8), 2265f60ed0dSThierry Reding GR3D_GLOBAL_SAMP23SURFADDR( 9), 2275f60ed0dSThierry Reding GR3D_GLOBAL_SAMP23SURFADDR(10), 2285f60ed0dSThierry Reding GR3D_GLOBAL_SAMP23SURFADDR(11), 2295f60ed0dSThierry Reding GR3D_GLOBAL_SAMP23SURFADDR(12), 2305f60ed0dSThierry Reding GR3D_GLOBAL_SAMP23SURFADDR(13), 2315f60ed0dSThierry Reding GR3D_GLOBAL_SAMP23SURFADDR(14), 2325f60ed0dSThierry Reding GR3D_GLOBAL_SAMP23SURFADDR(15), 2335f60ed0dSThierry Reding }; 2345f60ed0dSThierry Reding 2355f60ed0dSThierry Reding static int gr3d_probe(struct platform_device *pdev) 2365f60ed0dSThierry Reding { 2375f60ed0dSThierry Reding struct device_node *np = pdev->dev.of_node; 2385f60ed0dSThierry Reding struct host1x_syncpt **syncpts; 2395f60ed0dSThierry Reding struct gr3d *gr3d; 2405f60ed0dSThierry Reding unsigned int i; 2415f60ed0dSThierry Reding int err; 2425f60ed0dSThierry Reding 2435f60ed0dSThierry Reding gr3d = devm_kzalloc(&pdev->dev, sizeof(*gr3d), GFP_KERNEL); 2445f60ed0dSThierry Reding if (!gr3d) 2455f60ed0dSThierry Reding return -ENOMEM; 2465f60ed0dSThierry Reding 2475f60ed0dSThierry Reding syncpts = devm_kzalloc(&pdev->dev, sizeof(*syncpts), GFP_KERNEL); 2485f60ed0dSThierry Reding if (!syncpts) 2495f60ed0dSThierry Reding return -ENOMEM; 2505f60ed0dSThierry Reding 2515f60ed0dSThierry Reding gr3d->clk = devm_clk_get(&pdev->dev, NULL); 2525f60ed0dSThierry Reding if (IS_ERR(gr3d->clk)) { 2535f60ed0dSThierry Reding dev_err(&pdev->dev, "cannot get clock\n"); 2545f60ed0dSThierry Reding return PTR_ERR(gr3d->clk); 2555f60ed0dSThierry Reding } 2565f60ed0dSThierry Reding 2575f60ed0dSThierry Reding if (of_device_is_compatible(np, "nvidia,tegra30-gr3d")) { 2585f60ed0dSThierry Reding gr3d->clk_secondary = devm_clk_get(&pdev->dev, "3d2"); 2595f60ed0dSThierry Reding if (IS_ERR(gr3d->clk)) { 2605f60ed0dSThierry Reding dev_err(&pdev->dev, "cannot get secondary clock\n"); 2615f60ed0dSThierry Reding return PTR_ERR(gr3d->clk); 2625f60ed0dSThierry Reding } 2635f60ed0dSThierry Reding } 2645f60ed0dSThierry Reding 2655f60ed0dSThierry Reding err = tegra_powergate_sequence_power_up(TEGRA_POWERGATE_3D, gr3d->clk); 2665f60ed0dSThierry Reding if (err < 0) { 2675f60ed0dSThierry Reding dev_err(&pdev->dev, "failed to power up 3D unit\n"); 2685f60ed0dSThierry Reding return err; 2695f60ed0dSThierry Reding } 2705f60ed0dSThierry Reding 2715f60ed0dSThierry Reding if (gr3d->clk_secondary) { 2725f60ed0dSThierry Reding err = tegra_powergate_sequence_power_up(TEGRA_POWERGATE_3D1, 2735f60ed0dSThierry Reding gr3d->clk_secondary); 2745f60ed0dSThierry Reding if (err < 0) { 2755f60ed0dSThierry Reding dev_err(&pdev->dev, 2765f60ed0dSThierry Reding "failed to power up secondary 3D unit\n"); 2775f60ed0dSThierry Reding return err; 2785f60ed0dSThierry Reding } 2795f60ed0dSThierry Reding } 2805f60ed0dSThierry Reding 2815f60ed0dSThierry Reding INIT_LIST_HEAD(&gr3d->client.base.list); 2825f60ed0dSThierry Reding gr3d->client.base.ops = &gr3d_client_ops; 2835f60ed0dSThierry Reding gr3d->client.base.dev = &pdev->dev; 2845f60ed0dSThierry Reding gr3d->client.base.class = HOST1X_CLASS_GR3D; 2855f60ed0dSThierry Reding gr3d->client.base.syncpts = syncpts; 2865f60ed0dSThierry Reding gr3d->client.base.num_syncpts = 1; 2875f60ed0dSThierry Reding 2885f60ed0dSThierry Reding INIT_LIST_HEAD(&gr3d->client.list); 2895f60ed0dSThierry Reding gr3d->client.ops = &gr3d_ops; 2905f60ed0dSThierry Reding 2915f60ed0dSThierry Reding err = host1x_client_register(&gr3d->client.base); 2925f60ed0dSThierry Reding if (err < 0) { 2935f60ed0dSThierry Reding dev_err(&pdev->dev, "failed to register host1x client: %d\n", 2945f60ed0dSThierry Reding err); 2955f60ed0dSThierry Reding return err; 2965f60ed0dSThierry Reding } 2975f60ed0dSThierry Reding 2985f60ed0dSThierry Reding /* initialize address register map */ 2995f60ed0dSThierry Reding for (i = 0; i < ARRAY_SIZE(gr3d_addr_regs); i++) 3005f60ed0dSThierry Reding set_bit(gr3d_addr_regs[i], gr3d->addr_regs); 3015f60ed0dSThierry Reding 3025f60ed0dSThierry Reding platform_set_drvdata(pdev, gr3d); 3035f60ed0dSThierry Reding 3045f60ed0dSThierry Reding return 0; 3055f60ed0dSThierry Reding } 3065f60ed0dSThierry Reding 3075f60ed0dSThierry Reding static int gr3d_remove(struct platform_device *pdev) 3085f60ed0dSThierry Reding { 3095f60ed0dSThierry Reding struct gr3d *gr3d = platform_get_drvdata(pdev); 3105f60ed0dSThierry Reding int err; 3115f60ed0dSThierry Reding 3125f60ed0dSThierry Reding err = host1x_client_unregister(&gr3d->client.base); 3135f60ed0dSThierry Reding if (err < 0) { 3145f60ed0dSThierry Reding dev_err(&pdev->dev, "failed to unregister host1x client: %d\n", 3155f60ed0dSThierry Reding err); 3165f60ed0dSThierry Reding return err; 3175f60ed0dSThierry Reding } 3185f60ed0dSThierry Reding 3195f60ed0dSThierry Reding if (gr3d->clk_secondary) { 3205f60ed0dSThierry Reding tegra_powergate_power_off(TEGRA_POWERGATE_3D1); 3215f60ed0dSThierry Reding clk_disable_unprepare(gr3d->clk_secondary); 3225f60ed0dSThierry Reding } 3235f60ed0dSThierry Reding 3245f60ed0dSThierry Reding tegra_powergate_power_off(TEGRA_POWERGATE_3D); 3255f60ed0dSThierry Reding clk_disable_unprepare(gr3d->clk); 3265f60ed0dSThierry Reding 3275f60ed0dSThierry Reding return 0; 3285f60ed0dSThierry Reding } 3295f60ed0dSThierry Reding 3305f60ed0dSThierry Reding struct platform_driver tegra_gr3d_driver = { 3315f60ed0dSThierry Reding .driver = { 3325f60ed0dSThierry Reding .name = "tegra-gr3d", 3335f60ed0dSThierry Reding .of_match_table = tegra_gr3d_match, 3345f60ed0dSThierry Reding }, 3355f60ed0dSThierry Reding .probe = gr3d_probe, 3365f60ed0dSThierry Reding .remove = gr3d_remove, 3375f60ed0dSThierry Reding }; 338