root/drivers/gpu/drm/bridge/tc358764.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. tc358764_clear_error
  2. tc358764_read
  3. tc358764_write
  4. bridge_to_tc358764
  5. connector_to_tc358764
  6. tc358764_init
  7. tc358764_reset
  8. tc358764_get_modes
  9. tc358764_disable
  10. tc358764_post_disable
  11. tc358764_pre_enable
  12. tc358764_enable
  13. tc358764_attach
  14. tc358764_detach
  15. tc358764_parse_dt
  16. tc358764_configure_regulators
  17. tc358764_probe
  18. tc358764_remove

   1 // SPDX-License-Identifier: GPL-2.0
   2 /*
   3  * Copyright (C) 2018 Samsung Electronics Co., Ltd
   4  *
   5  * Authors:
   6  *      Andrzej Hajda <a.hajda@samsung.com>
   7  *      Maciej Purski <m.purski@samsung.com>
   8  */
   9 
  10 #include <linux/delay.h>
  11 #include <linux/gpio/consumer.h>
  12 #include <linux/module.h>
  13 #include <linux/of_graph.h>
  14 #include <linux/regulator/consumer.h>
  15 
  16 #include <video/mipi_display.h>
  17 
  18 #include <drm/drm_atomic_helper.h>
  19 #include <drm/drm_crtc.h>
  20 #include <drm/drm_fb_helper.h>
  21 #include <drm/drm_mipi_dsi.h>
  22 #include <drm/drm_of.h>
  23 #include <drm/drm_panel.h>
  24 #include <drm/drm_print.h>
  25 #include <drm/drm_probe_helper.h>
  26 
  27 #define FLD_MASK(start, end)    (((1 << ((start) - (end) + 1)) - 1) << (end))
  28 #define FLD_VAL(val, start, end) (((val) << (end)) & FLD_MASK(start, end))
  29 
  30 /* PPI layer registers */
  31 #define PPI_STARTPPI            0x0104 /* START control bit */
  32 #define PPI_LPTXTIMECNT         0x0114 /* LPTX timing signal */
  33 #define PPI_LANEENABLE          0x0134 /* Enables each lane */
  34 #define PPI_TX_RX_TA            0x013C /* BTA timing parameters */
  35 #define PPI_D0S_CLRSIPOCOUNT    0x0164 /* Assertion timer for Lane 0 */
  36 #define PPI_D1S_CLRSIPOCOUNT    0x0168 /* Assertion timer for Lane 1 */
  37 #define PPI_D2S_CLRSIPOCOUNT    0x016C /* Assertion timer for Lane 2 */
  38 #define PPI_D3S_CLRSIPOCOUNT    0x0170 /* Assertion timer for Lane 3 */
  39 #define PPI_START_FUNCTION      1
  40 
  41 /* DSI layer registers */
  42 #define DSI_STARTDSI            0x0204 /* START control bit of DSI-TX */
  43 #define DSI_LANEENABLE          0x0210 /* Enables each lane */
  44 #define DSI_RX_START            1
  45 
  46 /* Video path registers */
  47 #define VP_CTRL                 0x0450 /* Video Path Control */
  48 #define VP_CTRL_MSF(v)          FLD_VAL(v, 0, 0) /* Magic square in RGB666 */
  49 #define VP_CTRL_VTGEN(v)        FLD_VAL(v, 4, 4) /* Use chip clock for timing */
  50 #define VP_CTRL_EVTMODE(v)      FLD_VAL(v, 5, 5) /* Event mode */
  51 #define VP_CTRL_RGB888(v)       FLD_VAL(v, 8, 8) /* RGB888 mode */
  52 #define VP_CTRL_VSDELAY(v)      FLD_VAL(v, 31, 20) /* VSYNC delay */
  53 #define VP_CTRL_HSPOL           BIT(17) /* Polarity of HSYNC signal */
  54 #define VP_CTRL_DEPOL           BIT(18) /* Polarity of DE signal */
  55 #define VP_CTRL_VSPOL           BIT(19) /* Polarity of VSYNC signal */
  56 #define VP_HTIM1                0x0454 /* Horizontal Timing Control 1 */
  57 #define VP_HTIM1_HBP(v)         FLD_VAL(v, 24, 16)
  58 #define VP_HTIM1_HSYNC(v)       FLD_VAL(v, 8, 0)
  59 #define VP_HTIM2                0x0458 /* Horizontal Timing Control 2 */
  60 #define VP_HTIM2_HFP(v)         FLD_VAL(v, 24, 16)
  61 #define VP_HTIM2_HACT(v)        FLD_VAL(v, 10, 0)
  62 #define VP_VTIM1                0x045C /* Vertical Timing Control 1 */
  63 #define VP_VTIM1_VBP(v)         FLD_VAL(v, 23, 16)
  64 #define VP_VTIM1_VSYNC(v)       FLD_VAL(v, 7, 0)
  65 #define VP_VTIM2                0x0460 /* Vertical Timing Control 2 */
  66 #define VP_VTIM2_VFP(v)         FLD_VAL(v, 23, 16)
  67 #define VP_VTIM2_VACT(v)        FLD_VAL(v, 10, 0)
  68 #define VP_VFUEN                0x0464 /* Video Frame Timing Update Enable */
  69 
  70 /* LVDS registers */
  71 #define LV_MX0003               0x0480 /* Mux input bit 0 to 3 */
  72 #define LV_MX0407               0x0484 /* Mux input bit 4 to 7 */
  73 #define LV_MX0811               0x0488 /* Mux input bit 8 to 11 */
  74 #define LV_MX1215               0x048C /* Mux input bit 12 to 15 */
  75 #define LV_MX1619               0x0490 /* Mux input bit 16 to 19 */
  76 #define LV_MX2023               0x0494 /* Mux input bit 20 to 23 */
  77 #define LV_MX2427               0x0498 /* Mux input bit 24 to 27 */
  78 #define LV_MX(b0, b1, b2, b3)   (FLD_VAL(b0, 4, 0) | FLD_VAL(b1, 12, 8) | \
  79                                 FLD_VAL(b2, 20, 16) | FLD_VAL(b3, 28, 24))
  80 
  81 /* Input bit numbers used in mux registers */
  82 enum {
  83         LVI_R0,
  84         LVI_R1,
  85         LVI_R2,
  86         LVI_R3,
  87         LVI_R4,
  88         LVI_R5,
  89         LVI_R6,
  90         LVI_R7,
  91         LVI_G0,
  92         LVI_G1,
  93         LVI_G2,
  94         LVI_G3,
  95         LVI_G4,
  96         LVI_G5,
  97         LVI_G6,
  98         LVI_G7,
  99         LVI_B0,
 100         LVI_B1,
 101         LVI_B2,
 102         LVI_B3,
 103         LVI_B4,
 104         LVI_B5,
 105         LVI_B6,
 106         LVI_B7,
 107         LVI_HS,
 108         LVI_VS,
 109         LVI_DE,
 110         LVI_L0
 111 };
 112 
 113 #define LV_CFG                  0x049C /* LVDS Configuration */
 114 #define LV_PHY0                 0x04A0 /* LVDS PHY 0 */
 115 #define LV_PHY0_RST(v)          FLD_VAL(v, 22, 22) /* PHY reset */
 116 #define LV_PHY0_IS(v)           FLD_VAL(v, 15, 14)
 117 #define LV_PHY0_ND(v)           FLD_VAL(v, 4, 0) /* Frequency range select */
 118 #define LV_PHY0_PRBS_ON(v)      FLD_VAL(v, 20, 16) /* Clock/Data Flag pins */
 119 
 120 /* System registers */
 121 #define SYS_RST                 0x0504 /* System Reset */
 122 #define SYS_ID                  0x0580 /* System ID */
 123 
 124 #define SYS_RST_I2CS            BIT(0) /* Reset I2C-Slave controller */
 125 #define SYS_RST_I2CM            BIT(1) /* Reset I2C-Master controller */
 126 #define SYS_RST_LCD             BIT(2) /* Reset LCD controller */
 127 #define SYS_RST_BM              BIT(3) /* Reset Bus Management controller */
 128 #define SYS_RST_DSIRX           BIT(4) /* Reset DSI-RX and App controller */
 129 #define SYS_RST_REG             BIT(5) /* Reset Register module */
 130 
 131 #define LPX_PERIOD              2
 132 #define TTA_SURE                3
 133 #define TTA_GET                 0x20000
 134 
 135 /* Lane enable PPI and DSI register bits */
 136 #define LANEENABLE_CLEN         BIT(0)
 137 #define LANEENABLE_L0EN         BIT(1)
 138 #define LANEENABLE_L1EN         BIT(2)
 139 #define LANEENABLE_L2EN         BIT(3)
 140 #define LANEENABLE_L3EN         BIT(4)
 141 
 142 /* LVCFG fields */
 143 #define LV_CFG_LVEN             BIT(0)
 144 #define LV_CFG_LVDLINK          BIT(1)
 145 #define LV_CFG_CLKPOL1          BIT(2)
 146 #define LV_CFG_CLKPOL2          BIT(3)
 147 
 148 static const char * const tc358764_supplies[] = {
 149         "vddc", "vddio", "vddlvds"
 150 };
 151 
 152 struct tc358764 {
 153         struct device *dev;
 154         struct drm_bridge bridge;
 155         struct drm_connector connector;
 156         struct regulator_bulk_data supplies[ARRAY_SIZE(tc358764_supplies)];
 157         struct gpio_desc *gpio_reset;
 158         struct drm_panel *panel;
 159         int error;
 160 };
 161 
 162 static int tc358764_clear_error(struct tc358764 *ctx)
 163 {
 164         int ret = ctx->error;
 165 
 166         ctx->error = 0;
 167         return ret;
 168 }
 169 
 170 static void tc358764_read(struct tc358764 *ctx, u16 addr, u32 *val)
 171 {
 172         struct mipi_dsi_device *dsi = to_mipi_dsi_device(ctx->dev);
 173         ssize_t ret;
 174 
 175         if (ctx->error)
 176                 return;
 177 
 178         cpu_to_le16s(&addr);
 179         ret = mipi_dsi_generic_read(dsi, &addr, sizeof(addr), val, sizeof(*val));
 180         if (ret >= 0)
 181                 le32_to_cpus(val);
 182 
 183         dev_dbg(ctx->dev, "read: %d, addr: %d\n", addr, *val);
 184 }
 185 
 186 static void tc358764_write(struct tc358764 *ctx, u16 addr, u32 val)
 187 {
 188         struct mipi_dsi_device *dsi = to_mipi_dsi_device(ctx->dev);
 189         ssize_t ret;
 190         u8 data[6];
 191 
 192         if (ctx->error)
 193                 return;
 194 
 195         data[0] = addr;
 196         data[1] = addr >> 8;
 197         data[2] = val;
 198         data[3] = val >> 8;
 199         data[4] = val >> 16;
 200         data[5] = val >> 24;
 201 
 202         ret = mipi_dsi_generic_write(dsi, data, sizeof(data));
 203         if (ret < 0)
 204                 ctx->error = ret;
 205 }
 206 
 207 static inline struct tc358764 *bridge_to_tc358764(struct drm_bridge *bridge)
 208 {
 209         return container_of(bridge, struct tc358764, bridge);
 210 }
 211 
 212 static inline
 213 struct tc358764 *connector_to_tc358764(struct drm_connector *connector)
 214 {
 215         return container_of(connector, struct tc358764, connector);
 216 }
 217 
 218 static int tc358764_init(struct tc358764 *ctx)
 219 {
 220         u32 v = 0;
 221 
 222         tc358764_read(ctx, SYS_ID, &v);
 223         if (ctx->error)
 224                 return tc358764_clear_error(ctx);
 225         dev_info(ctx->dev, "ID: %#x\n", v);
 226 
 227         /* configure PPI counters */
 228         tc358764_write(ctx, PPI_TX_RX_TA, TTA_GET | TTA_SURE);
 229         tc358764_write(ctx, PPI_LPTXTIMECNT, LPX_PERIOD);
 230         tc358764_write(ctx, PPI_D0S_CLRSIPOCOUNT, 5);
 231         tc358764_write(ctx, PPI_D1S_CLRSIPOCOUNT, 5);
 232         tc358764_write(ctx, PPI_D2S_CLRSIPOCOUNT, 5);
 233         tc358764_write(ctx, PPI_D3S_CLRSIPOCOUNT, 5);
 234 
 235         /* enable four data lanes and clock lane */
 236         tc358764_write(ctx, PPI_LANEENABLE, LANEENABLE_L3EN | LANEENABLE_L2EN |
 237                        LANEENABLE_L1EN | LANEENABLE_L0EN | LANEENABLE_CLEN);
 238         tc358764_write(ctx, DSI_LANEENABLE, LANEENABLE_L3EN | LANEENABLE_L2EN |
 239                        LANEENABLE_L1EN | LANEENABLE_L0EN | LANEENABLE_CLEN);
 240 
 241         /* start */
 242         tc358764_write(ctx, PPI_STARTPPI, PPI_START_FUNCTION);
 243         tc358764_write(ctx, DSI_STARTDSI, DSI_RX_START);
 244 
 245         /* configure video path */
 246         tc358764_write(ctx, VP_CTRL, VP_CTRL_VSDELAY(15) | VP_CTRL_RGB888(1) |
 247                        VP_CTRL_EVTMODE(1) | VP_CTRL_HSPOL | VP_CTRL_VSPOL);
 248 
 249         /* reset PHY */
 250         tc358764_write(ctx, LV_PHY0, LV_PHY0_RST(1) |
 251                        LV_PHY0_PRBS_ON(4) | LV_PHY0_IS(2) | LV_PHY0_ND(6));
 252         tc358764_write(ctx, LV_PHY0, LV_PHY0_PRBS_ON(4) | LV_PHY0_IS(2) |
 253                        LV_PHY0_ND(6));
 254 
 255         /* reset bridge */
 256         tc358764_write(ctx, SYS_RST, SYS_RST_LCD);
 257 
 258         /* set bit order */
 259         tc358764_write(ctx, LV_MX0003, LV_MX(LVI_R0, LVI_R1, LVI_R2, LVI_R3));
 260         tc358764_write(ctx, LV_MX0407, LV_MX(LVI_R4, LVI_R7, LVI_R5, LVI_G0));
 261         tc358764_write(ctx, LV_MX0811, LV_MX(LVI_G1, LVI_G2, LVI_G6, LVI_G7));
 262         tc358764_write(ctx, LV_MX1215, LV_MX(LVI_G3, LVI_G4, LVI_G5, LVI_B0));
 263         tc358764_write(ctx, LV_MX1619, LV_MX(LVI_B6, LVI_B7, LVI_B1, LVI_B2));
 264         tc358764_write(ctx, LV_MX2023, LV_MX(LVI_B3, LVI_B4, LVI_B5, LVI_L0));
 265         tc358764_write(ctx, LV_MX2427, LV_MX(LVI_HS, LVI_VS, LVI_DE, LVI_R6));
 266         tc358764_write(ctx, LV_CFG, LV_CFG_CLKPOL2 | LV_CFG_CLKPOL1 |
 267                        LV_CFG_LVEN);
 268 
 269         return tc358764_clear_error(ctx);
 270 }
 271 
 272 static void tc358764_reset(struct tc358764 *ctx)
 273 {
 274         gpiod_set_value(ctx->gpio_reset, 1);
 275         usleep_range(1000, 2000);
 276         gpiod_set_value(ctx->gpio_reset, 0);
 277         usleep_range(1000, 2000);
 278 }
 279 
 280 static int tc358764_get_modes(struct drm_connector *connector)
 281 {
 282         struct tc358764 *ctx = connector_to_tc358764(connector);
 283 
 284         return drm_panel_get_modes(ctx->panel);
 285 }
 286 
 287 static const
 288 struct drm_connector_helper_funcs tc358764_connector_helper_funcs = {
 289         .get_modes = tc358764_get_modes,
 290 };
 291 
 292 static const struct drm_connector_funcs tc358764_connector_funcs = {
 293         .fill_modes = drm_helper_probe_single_connector_modes,
 294         .destroy = drm_connector_cleanup,
 295         .reset = drm_atomic_helper_connector_reset,
 296         .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
 297         .atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
 298 };
 299 
 300 static void tc358764_disable(struct drm_bridge *bridge)
 301 {
 302         struct tc358764 *ctx = bridge_to_tc358764(bridge);
 303         int ret = drm_panel_disable(bridge_to_tc358764(bridge)->panel);
 304 
 305         if (ret < 0)
 306                 dev_err(ctx->dev, "error disabling panel (%d)\n", ret);
 307 }
 308 
 309 static void tc358764_post_disable(struct drm_bridge *bridge)
 310 {
 311         struct tc358764 *ctx = bridge_to_tc358764(bridge);
 312         int ret;
 313 
 314         ret = drm_panel_unprepare(ctx->panel);
 315         if (ret < 0)
 316                 dev_err(ctx->dev, "error unpreparing panel (%d)\n", ret);
 317         tc358764_reset(ctx);
 318         usleep_range(10000, 15000);
 319         ret = regulator_bulk_disable(ARRAY_SIZE(ctx->supplies), ctx->supplies);
 320         if (ret < 0)
 321                 dev_err(ctx->dev, "error disabling regulators (%d)\n", ret);
 322 }
 323 
 324 static void tc358764_pre_enable(struct drm_bridge *bridge)
 325 {
 326         struct tc358764 *ctx = bridge_to_tc358764(bridge);
 327         int ret;
 328 
 329         ret = regulator_bulk_enable(ARRAY_SIZE(ctx->supplies), ctx->supplies);
 330         if (ret < 0)
 331                 dev_err(ctx->dev, "error enabling regulators (%d)\n", ret);
 332         usleep_range(10000, 15000);
 333         tc358764_reset(ctx);
 334         ret = tc358764_init(ctx);
 335         if (ret < 0)
 336                 dev_err(ctx->dev, "error initializing bridge (%d)\n", ret);
 337         ret = drm_panel_prepare(ctx->panel);
 338         if (ret < 0)
 339                 dev_err(ctx->dev, "error preparing panel (%d)\n", ret);
 340 }
 341 
 342 static void tc358764_enable(struct drm_bridge *bridge)
 343 {
 344         struct tc358764 *ctx = bridge_to_tc358764(bridge);
 345         int ret = drm_panel_enable(ctx->panel);
 346 
 347         if (ret < 0)
 348                 dev_err(ctx->dev, "error enabling panel (%d)\n", ret);
 349 }
 350 
 351 static int tc358764_attach(struct drm_bridge *bridge)
 352 {
 353         struct tc358764 *ctx = bridge_to_tc358764(bridge);
 354         struct drm_device *drm = bridge->dev;
 355         int ret;
 356 
 357         ctx->connector.polled = DRM_CONNECTOR_POLL_HPD;
 358         ret = drm_connector_init(drm, &ctx->connector,
 359                                  &tc358764_connector_funcs,
 360                                  DRM_MODE_CONNECTOR_LVDS);
 361         if (ret) {
 362                 DRM_ERROR("Failed to initialize connector\n");
 363                 return ret;
 364         }
 365 
 366         drm_connector_helper_add(&ctx->connector,
 367                                  &tc358764_connector_helper_funcs);
 368         drm_connector_attach_encoder(&ctx->connector, bridge->encoder);
 369         drm_panel_attach(ctx->panel, &ctx->connector);
 370         ctx->connector.funcs->reset(&ctx->connector);
 371         drm_fb_helper_add_one_connector(drm->fb_helper, &ctx->connector);
 372         drm_connector_register(&ctx->connector);
 373 
 374         return 0;
 375 }
 376 
 377 static void tc358764_detach(struct drm_bridge *bridge)
 378 {
 379         struct tc358764 *ctx = bridge_to_tc358764(bridge);
 380         struct drm_device *drm = bridge->dev;
 381 
 382         drm_connector_unregister(&ctx->connector);
 383         drm_fb_helper_remove_one_connector(drm->fb_helper, &ctx->connector);
 384         drm_panel_detach(ctx->panel);
 385         ctx->panel = NULL;
 386         drm_connector_put(&ctx->connector);
 387 }
 388 
 389 static const struct drm_bridge_funcs tc358764_bridge_funcs = {
 390         .disable = tc358764_disable,
 391         .post_disable = tc358764_post_disable,
 392         .enable = tc358764_enable,
 393         .pre_enable = tc358764_pre_enable,
 394         .attach = tc358764_attach,
 395         .detach = tc358764_detach,
 396 };
 397 
 398 static int tc358764_parse_dt(struct tc358764 *ctx)
 399 {
 400         struct device *dev = ctx->dev;
 401         int ret;
 402 
 403         ctx->gpio_reset = devm_gpiod_get(dev, "reset", GPIOD_OUT_LOW);
 404         if (IS_ERR(ctx->gpio_reset)) {
 405                 dev_err(dev, "no reset GPIO pin provided\n");
 406                 return PTR_ERR(ctx->gpio_reset);
 407         }
 408 
 409         ret = drm_of_find_panel_or_bridge(ctx->dev->of_node, 1, 0, &ctx->panel,
 410                                           NULL);
 411         if (ret && ret != -EPROBE_DEFER)
 412                 dev_err(dev, "cannot find panel (%d)\n", ret);
 413 
 414         return ret;
 415 }
 416 
 417 static int tc358764_configure_regulators(struct tc358764 *ctx)
 418 {
 419         int i, ret;
 420 
 421         for (i = 0; i < ARRAY_SIZE(ctx->supplies); ++i)
 422                 ctx->supplies[i].supply = tc358764_supplies[i];
 423 
 424         ret = devm_regulator_bulk_get(ctx->dev, ARRAY_SIZE(ctx->supplies),
 425                                       ctx->supplies);
 426         if (ret < 0)
 427                 dev_err(ctx->dev, "failed to get regulators: %d\n", ret);
 428 
 429         return ret;
 430 }
 431 
 432 static int tc358764_probe(struct mipi_dsi_device *dsi)
 433 {
 434         struct device *dev = &dsi->dev;
 435         struct tc358764 *ctx;
 436         int ret;
 437 
 438         ctx = devm_kzalloc(dev, sizeof(struct tc358764), GFP_KERNEL);
 439         if (!ctx)
 440                 return -ENOMEM;
 441 
 442         mipi_dsi_set_drvdata(dsi, ctx);
 443 
 444         ctx->dev = dev;
 445 
 446         dsi->lanes = 4;
 447         dsi->format = MIPI_DSI_FMT_RGB888;
 448         dsi->mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_BURST
 449                 | MIPI_DSI_MODE_VIDEO_AUTO_VERT | MIPI_DSI_MODE_LPM;
 450 
 451         ret = tc358764_parse_dt(ctx);
 452         if (ret < 0)
 453                 return ret;
 454 
 455         ret = tc358764_configure_regulators(ctx);
 456         if (ret < 0)
 457                 return ret;
 458 
 459         ctx->bridge.funcs = &tc358764_bridge_funcs;
 460         ctx->bridge.of_node = dev->of_node;
 461 
 462         drm_bridge_add(&ctx->bridge);
 463 
 464         ret = mipi_dsi_attach(dsi);
 465         if (ret < 0) {
 466                 drm_bridge_remove(&ctx->bridge);
 467                 dev_err(dev, "failed to attach dsi\n");
 468         }
 469 
 470         return ret;
 471 }
 472 
 473 static int tc358764_remove(struct mipi_dsi_device *dsi)
 474 {
 475         struct tc358764 *ctx = mipi_dsi_get_drvdata(dsi);
 476 
 477         mipi_dsi_detach(dsi);
 478         drm_bridge_remove(&ctx->bridge);
 479 
 480         return 0;
 481 }
 482 
 483 static const struct of_device_id tc358764_of_match[] = {
 484         { .compatible = "toshiba,tc358764" },
 485         { }
 486 };
 487 MODULE_DEVICE_TABLE(of, tc358764_of_match);
 488 
 489 static struct mipi_dsi_driver tc358764_driver = {
 490         .probe = tc358764_probe,
 491         .remove = tc358764_remove,
 492         .driver = {
 493                 .name = "tc358764",
 494                 .owner = THIS_MODULE,
 495                 .of_match_table = tc358764_of_match,
 496         },
 497 };
 498 module_mipi_dsi_driver(tc358764_driver);
 499 
 500 MODULE_AUTHOR("Andrzej Hajda <a.hajda@samsung.com>");
 501 MODULE_AUTHOR("Maciej Purski <m.purski@samsung.com>");
 502 MODULE_DESCRIPTION("MIPI-DSI based Driver for TC358764 DSI/LVDS Bridge");
 503 MODULE_LICENSE("GPL v2");

/* [<][>][^][v][top][bottom][index][help] */