|
2 | 2 | from __future__ import annotations |
3 | 3 |
|
4 | 4 | import datetime |
| 5 | + |
5 | 6 | import mipi |
6 | 7 | import simple |
7 | 8 | import wrap |
8 | | -from generator import Options |
| 9 | +from generator import Options, GpioFlag |
9 | 10 | from panel import Panel, BacklightControl, CommandSequence |
10 | 11 |
|
11 | 12 |
|
@@ -59,7 +60,7 @@ def generate_struct(p: Panel, options: Options) -> str: |
59 | 60 | variables.append(f'struct regulator_bulk_data supplies[{len(options.regulator)}]') |
60 | 61 | else: |
61 | 62 | variables.append('struct regulator *supply') |
62 | | - variables += [f'struct gpio_desc *{name}_gpio' for name in options.gpios] |
| 63 | + variables += [f'struct gpio_desc *{name}_gpio' for name in options.gpios.keys()] |
63 | 64 | variables.append('bool prepared') |
64 | 65 |
|
65 | 66 | s = f'struct {p.short_id} {{' |
@@ -109,12 +110,15 @@ def msleep(m: int) -> str: |
109 | 110 | return f"usleep_range({u}, {u + 1000})" |
110 | 111 |
|
111 | 112 |
|
112 | | -def generate_reset(p: Panel) -> str: |
| 113 | +def generate_reset(p: Panel, options: Options) -> str: |
113 | 114 | if not p.reset_seq: |
114 | 115 | return '' |
115 | 116 |
|
116 | 117 | s = f'\nstatic void {p.short_id}_reset(struct {p.short_id} *ctx)\n{{\n' |
117 | 118 | for state, sleep in p.reset_seq: |
| 119 | + # Invert reset sequence if GPIO is active low |
| 120 | + if options.gpios["reset"] & GpioFlag.ACTIVE_LOW: |
| 121 | + state = int(not bool(state)) |
118 | 122 | s += f'\tgpiod_set_value_cansleep(ctx->reset_gpio, {state});\n' |
119 | 123 | if sleep: |
120 | 124 | s += f'\t{msleep(sleep)};\n' |
@@ -165,7 +169,7 @@ def generate_commands(p: Panel, options: Options, cmd_name: str) -> str: |
165 | 169 | def generate_cleanup(p: Panel, options: Options, indent: int = 1) -> str: |
166 | 170 | cleanup = [] |
167 | 171 | if p.reset_seq: |
168 | | - cleanup.append('gpiod_set_value_cansleep(ctx->reset_gpio, 0);') |
| 172 | + cleanup.append('gpiod_set_value_cansleep(ctx->reset_gpio, 1);') |
169 | 173 | if options.regulator: |
170 | 174 | if len(options.regulator) > 1: |
171 | 175 | cleanup.append('regulator_bulk_disable(ARRAY_SIZE(ctx->supplies), ctx->supplies);') |
@@ -370,9 +374,14 @@ def generate_probe(p: Panel, options: Options) -> str: |
370 | 374 | }} |
371 | 375 | ''' |
372 | 376 |
|
373 | | - for name in options.gpios: |
| 377 | + for name, flags in options.gpios.items(): |
| 378 | + # TODO: In the future, we might want to change this to keep panel alive |
| 379 | + init = "GPIOD_OUT_LOW" |
| 380 | + if name == "reset": |
| 381 | + init = "GPIOD_OUT_HIGH" |
| 382 | + |
374 | 383 | s += f''' |
375 | | - ctx->{name}_gpio = devm_gpiod_get(dev, "{name}", GPIOD_OUT_LOW); |
| 384 | + ctx->{name}_gpio = devm_gpiod_get(dev, "{name}", {init}); |
376 | 385 | if (IS_ERR(ctx->{name}_gpio)) {{ |
377 | 386 | ret = PTR_ERR(ctx->{name}_gpio); |
378 | 387 | dev_err(dev, "Failed to get {name}-gpios: %d\\n", ret); |
@@ -436,11 +445,24 @@ def generate_driver(p: Panel, options: Options) -> None: |
436 | 445 | c.generated = c.type.generate(c.payload, options) |
437 | 446 | cmd.generated += c.generated |
438 | 447 |
|
439 | | - options.gpios = [] |
| 448 | + options.gpios = {} |
440 | 449 | if p.reset_seq: |
441 | | - options.gpios.append('reset') |
| 450 | + # Many panels have active low reset GPIOs. This can be seen if we keep |
| 451 | + # reset high after turning the panel on. From a logical perspective this |
| 452 | + # does not make sense: We should assert reset to actually do the reset, |
| 453 | + # not to disable it. |
| 454 | + # |
| 455 | + # Therefore we try check the last element from the reset sequence here. |
| 456 | + # If it sets the GPIO to 1 (high), we assume that reset is active low. |
| 457 | + |
| 458 | + flag = GpioFlag.ACTIVE_HIGH |
| 459 | + last_val, _ = p.reset_seq[-1] |
| 460 | + if last_val == 1: |
| 461 | + flag = GpioFlag.ACTIVE_LOW |
| 462 | + |
| 463 | + options.gpios["reset"] = flag |
442 | 464 | if options.backlight_gpio: |
443 | | - options.gpios.append('backlight') |
| 465 | + options.gpios["backlight"] = GpioFlag.ACTIVE_HIGH |
444 | 466 |
|
445 | 467 | dash_id = p.short_id.replace('_', '-') |
446 | 468 | compatible = dash_id.split('-', 1) |
@@ -469,7 +491,7 @@ def generate_driver(p: Panel, options: Options) -> None: |
469 | 491 | {{ |
470 | 492 | return container_of(panel, struct {p.short_id}, panel); |
471 | 493 | }}{generate_macros(p)} |
472 | | -{generate_reset(p)} |
| 494 | +{generate_reset(p, options)} |
473 | 495 | {generate_commands(p, options, 'on')} |
474 | 496 | {generate_commands(p, options, 'off')} |
475 | 497 | {generate_prepare(p, options)} |
|
0 commit comments