Landfall

Changeset

133:64fb2fa99680
2021-01-31 Paul Boddie raw files shortlog changelog graph Introduced generic clock frequency control methods to the CPM library and device, used by the LCD and HDMI devices and some examples. idl4re-libipc-libsystypes
pkg/devices/cpm/src/jz4730/cpm-jz4730.cc (file) pkg/devices/cpm/src/jz4740/cpm-jz4740.cc (file) pkg/devices/cpm/src/jz4780/cpm-jz4780.cc (file) pkg/devices/display/src/ci20/display-ci20_hdmi.cc (file) pkg/devices/idl/cpm.idl (file) pkg/devices/include/clocks.h (file) pkg/devices/lcd/src/jz4740/lcd-jz4740-device.cc (file) pkg/devices/lib/cpm/include/cpm-jz4730.h (file) pkg/devices/lib/cpm/include/cpm-jz4740.h (file) pkg/devices/lib/cpm/include/cpm-jz4780.h (file) pkg/devices/lib/cpm/include/cpm.h (file) pkg/devices/lib/cpm/src/jz4730.cc (file) pkg/devices/lib/cpm/src/jz4740.cc (file) pkg/devices/lib/cpm/src/jz4780.cc (file) pkg/landfall-examples/ci20_cpm/ci20_cpm.c (file) pkg/landfall-examples/ci20_hdmi_i2c/ci20_hdmi_i2c.c (file)
     1.1 --- a/pkg/devices/cpm/src/jz4730/cpm-jz4730.cc	Sat Jan 30 23:39:17 2021 +0100
     1.2 +++ b/pkg/devices/cpm/src/jz4730/cpm-jz4730.cc	Sun Jan 31 00:49:22 2021 +0100
     1.3 @@ -57,9 +57,9 @@
     1.4    {
     1.5    }
     1.6  
     1.7 -  long set_lcd_frequencies(uint32_t pclk, uint8_t multiplier)
     1.8 +  long set_frequency(enum Clock_frequency_identifiers clock, uint32_t frequency)
     1.9    {
    1.10 -    _chip->set_lcd_frequencies(pclk, multiplier);
    1.11 +    _chip->set_frequency(clock, frequency);
    1.12      return L4_EOK;
    1.13    }
    1.14  
     2.1 --- a/pkg/devices/cpm/src/jz4740/cpm-jz4740.cc	Sat Jan 30 23:39:17 2021 +0100
     2.2 +++ b/pkg/devices/cpm/src/jz4740/cpm-jz4740.cc	Sun Jan 31 00:49:22 2021 +0100
     2.3 @@ -57,9 +57,9 @@
     2.4    {
     2.5    }
     2.6  
     2.7 -  long set_lcd_frequencies(uint32_t pclk, uint8_t multiplier)
     2.8 +  long set_frequency(enum Clock_frequency_identifiers clock, uint32_t frequency)
     2.9    {
    2.10 -    _chip->set_lcd_frequencies(pclk, multiplier);
    2.11 +    _chip->set_frequency(clock, frequency);
    2.12      return L4_EOK;
    2.13    }
    2.14  
     3.1 --- a/pkg/devices/cpm/src/jz4780/cpm-jz4780.cc	Sat Jan 30 23:39:17 2021 +0100
     3.2 +++ b/pkg/devices/cpm/src/jz4780/cpm-jz4780.cc	Sun Jan 31 00:49:22 2021 +0100
     3.3 @@ -57,21 +57,15 @@
     3.4    {
     3.5    }
     3.6  
     3.7 -  long get_lcd_pixel_frequency(uint8_t controller, uint32_t *frequency)
     3.8 +  long get_frequency(enum Clock_frequency_identifiers clock, uint32_t *frequency)
     3.9    {
    3.10 -    *frequency = _chip->get_lcd_pixel_frequency(controller);
    3.11 +    *frequency = _chip->get_frequency(clock);
    3.12      return L4_EOK;
    3.13    }
    3.14  
    3.15 -  long set_hdmi_frequency(uint32_t frequency)
    3.16 +  long set_frequency(enum Clock_frequency_identifiers clock, uint32_t frequency)
    3.17    {
    3.18 -    _chip->set_hdmi_frequency(frequency);
    3.19 -    return L4_EOK;
    3.20 -  }
    3.21 -
    3.22 -  long set_lcd_frequencies(uint32_t pclk, uint8_t multiplier)
    3.23 -  {
    3.24 -    _chip->set_lcd_frequencies(pclk, multiplier);
    3.25 +    _chip->set_frequency(clock, frequency);
    3.26      return L4_EOK;
    3.27    }
    3.28  
     4.1 --- a/pkg/devices/display/src/ci20/display-ci20_hdmi.cc	Sat Jan 30 23:39:17 2021 +0100
     4.2 +++ b/pkg/devices/display/src/ci20/display-ci20_hdmi.cc	Sun Jan 31 00:49:22 2021 +0100
     4.3 @@ -1,7 +1,7 @@
     4.4  /*
     4.5   * Export MIPS Creator CI20 HDMI display operations as a server.
     4.6   *
     4.7 - * Copyright (C) 2018, 2020 Paul Boddie <paul@boddie.org.uk>
     4.8 + * Copyright (C) 2018, 2020, 2021 Paul Boddie <paul@boddie.org.uk>
     4.9   *
    4.10   * This program is free software; you can redistribute it and/or
    4.11   * modify it under the terms of the GNU General Public License as
    4.12 @@ -65,7 +65,7 @@
    4.13    /* Start the HDMI peripheral. */
    4.14  
    4.15    cpm_device->stop_clock(Clock_hdmi);
    4.16 -  cpm_device->set_hdmi_frequency(27000000);
    4.17 +  cpm_device->set_frequency(Clock_frequency_hdmi, 27000000);
    4.18    cpm_device->start_clock(Clock_hdmi);
    4.19  
    4.20    /* Load the panel data from the configured library. */
    4.21 @@ -119,7 +119,7 @@
    4.22  
    4.23      // NOTE: Should test to see if it is connected.
    4.24  
    4.25 -    if (!cpm_device->get_lcd_pixel_frequency(0, &frequency))
    4.26 +    if (!cpm_device->get_frequency(Clock_frequency_lcd_pixel, &frequency))
    4.27      {
    4.28        hdmi->enable(frequency);
    4.29      }
     5.1 --- a/pkg/devices/idl/cpm.idl	Sat Jan 30 23:39:17 2021 +0100
     5.2 +++ b/pkg/devices/idl/cpm.idl	Sun Jan 31 00:49:22 2021 +0100
     5.3 @@ -8,11 +8,9 @@
     5.4  [protocol(LANDFALL_CPM)]
     5.5  interface CPM
     5.6  {
     5.7 -  void get_lcd_pixel_frequency(in uint8_t controller, out uint32_t frequency);
     5.8 +  void get_frequency(in enum Clock_frequency_identifiers clock, out uint32_t frequency);
     5.9  
    5.10 -  void set_hdmi_frequency(in uint32_t frequency);
    5.11 -
    5.12 -  void set_lcd_frequencies(in uint32_t pclk, in uint8_t multiplier);
    5.13 +  void set_frequency(in enum Clock_frequency_identifiers clock, in uint32_t frequency);
    5.14  
    5.15    void have_clock(in enum Clock_identifiers clock, out int enabled);
    5.16  
     6.1 --- a/pkg/devices/include/clocks.h	Sat Jan 30 23:39:17 2021 +0100
     6.2 +++ b/pkg/devices/include/clocks.h	Sun Jan 31 00:49:22 2021 +0100
     6.3 @@ -21,6 +21,10 @@
     6.4  
     6.5  #pragma once
     6.6  
     6.7 +/* Identifiers for controllable "logical" or "abstract" clocks. Operations
     6.8 +   involving these clocks may operate on multiple "physical" or "specific"
     6.9 +   clocks. */
    6.10 +
    6.11  enum Clock_identifiers
    6.12  {
    6.13    Clock_aic_bitclk,
    6.14 @@ -52,4 +56,13 @@
    6.15    Clock_uprt,
    6.16  };
    6.17  
    6.18 +/* Identifiers for clocks whose frequencies can be adjusted or inspected. */
    6.19 +
    6.20 +enum Clock_frequency_identifiers
    6.21 +{
    6.22 +  Clock_frequency_lcd,
    6.23 +  Clock_frequency_lcd_pixel,
    6.24 +  Clock_frequency_hdmi,
    6.25 +};
    6.26 +
    6.27  // vim: tabstop=2 expandtab shiftwidth=2
     7.1 --- a/pkg/devices/lcd/src/jz4740/lcd-jz4740-device.cc	Sat Jan 30 23:39:17 2021 +0100
     7.2 +++ b/pkg/devices/lcd/src/jz4740/lcd-jz4740-device.cc	Sun Jan 31 00:49:22 2021 +0100
     7.3 @@ -64,7 +64,8 @@
     7.4    // 1.5 times that of the pixel clock, and a STN panel needs a device clock 3
     7.5    // times that of the pixel clock.
     7.6  
     7.7 -  cpm_device->set_lcd_frequencies(pclk, 3);
     7.8 +  cpm_device->set_frequency(Clock_frequency_lcd, pclk * 3);
     7.9 +  cpm_device->set_frequency(Clock_frequency_lcd_pixel, pclk);
    7.10    cpm_device->update_output_frequency();
    7.11    cpm_device->start_clock(Clock_lcd);
    7.12  
     8.1 --- a/pkg/devices/lib/cpm/include/cpm-jz4730.h	Sat Jan 30 23:39:17 2021 +0100
     8.2 +++ b/pkg/devices/lib/cpm/include/cpm-jz4730.h	Sun Jan 31 00:49:22 2021 +0100
     8.3 @@ -21,7 +21,7 @@
     8.4  
     8.5  #pragma once
     8.6  
     8.7 -#include "cpm.h"
     8.8 +#include <l4/devices/cpm.h>
     8.9  
    8.10  #include <l4/sys/types.h>
    8.11  #include <stdint.h>
    8.12 @@ -66,11 +66,12 @@
    8.13    uint8_t get_source_divider();
    8.14  
    8.15    uint16_t get_lcd_pixel_divider();
    8.16 -  uint32_t get_lcd_pixel_frequency();
    8.17  
    8.18    void set_lcd_device_divider(uint8_t division);
    8.19    void set_lcd_pixel_divider(uint16_t division);
    8.20 -  void set_lcd_frequencies(uint32_t pclk, uint8_t ratio);
    8.21 +
    8.22 +  uint32_t get_frequency(enum Clock_frequency_identifiers clock);
    8.23 +  void set_frequency(enum Clock_frequency_identifiers clock, uint32_t frequency);
    8.24  
    8.25    int have_clock(enum Clock_identifiers clock);
    8.26    void start_clock(enum Clock_identifiers clock);
    8.27 @@ -103,9 +104,10 @@
    8.28  void jz4730_cpm_stop_clock(void *cpm, enum Clock_identifiers clock);
    8.29  
    8.30  uint16_t jz4730_cpm_get_lcd_pixel_divider(void *cpm);
    8.31 -uint32_t jz4730_cpm_get_lcd_pixel_frequency(void *cpm);
    8.32  
    8.33 -void jz4730_cpm_set_lcd_frequencies(void *cpm, uint32_t pclk, uint8_t ratio);
    8.34 +uint32_t jz4730_cpm_get_frequency(void *cpm, enum Clock_frequency_identifiers clock);
    8.35 +void jz4730_cpm_set_frequency(void *cpm, enum Clock_frequency_identifiers clock, uint32_t frequency);
    8.36 +
    8.37  void jz4730_cpm_update_output_frequency(void *cpm);
    8.38  
    8.39  uint32_t jz4730_cpm_get_cpu_frequency(void *cpm);
     9.1 --- a/pkg/devices/lib/cpm/include/cpm-jz4740.h	Sat Jan 30 23:39:17 2021 +0100
     9.2 +++ b/pkg/devices/lib/cpm/include/cpm-jz4740.h	Sun Jan 31 00:49:22 2021 +0100
     9.3 @@ -21,7 +21,7 @@
     9.4  
     9.5  #pragma once
     9.6  
     9.7 -#include "cpm.h"
     9.8 +#include <l4/devices/cpm.h>
     9.9  
    9.10  #include <l4/sys/types.h>
    9.11  #include <stdint.h>
    9.12 @@ -70,11 +70,12 @@
    9.13    uint8_t get_source_divider();
    9.14  
    9.15    uint16_t get_lcd_pixel_divider();
    9.16 -  uint32_t get_lcd_pixel_frequency();
    9.17  
    9.18    void set_lcd_device_divider(uint8_t division);
    9.19    void set_lcd_pixel_divider(uint16_t division);
    9.20 -  void set_lcd_frequencies(uint32_t pclk, uint8_t ratio);
    9.21 +
    9.22 +  uint32_t get_frequency(enum Clock_frequency_identifiers clock);
    9.23 +  void set_frequency(enum Clock_frequency_identifiers clock, uint32_t frequency);
    9.24  
    9.25    uint32_t get_pll_frequency();
    9.26    uint32_t get_output_frequency();
    9.27 @@ -103,9 +104,10 @@
    9.28  void jz4740_cpm_stop_clock(void *cpm, enum Clock_identifiers clock);
    9.29  
    9.30  uint16_t jz4740_cpm_get_lcd_pixel_divider(void *cpm);
    9.31 -uint32_t jz4740_cpm_get_lcd_pixel_frequency(void *cpm);
    9.32  
    9.33 -void jz4740_cpm_set_lcd_frequencies(void *cpm, uint32_t pclk, uint8_t ratio);
    9.34 +uint32_t jz4740_cpm_get_frequency(void *cpm, enum Clock_frequency_identifiers clock);
    9.35 +void jz4740_cpm_set_frequency(void *cpm, enum Clock_frequency_identifiers clock, uint32_t frequency);
    9.36 +
    9.37  void jz4740_cpm_update_output_frequency(void *cpm);
    9.38  
    9.39  uint32_t jz4740_cpm_get_cpu_frequency(void *cpm);
    10.1 --- a/pkg/devices/lib/cpm/include/cpm-jz4780.h	Sat Jan 30 23:39:17 2021 +0100
    10.2 +++ b/pkg/devices/lib/cpm/include/cpm-jz4780.h	Sun Jan 31 00:49:22 2021 +0100
    10.3 @@ -21,7 +21,7 @@
    10.4  
    10.5  #pragma once
    10.6  
    10.7 -#include "cpm.h"
    10.8 +#include <l4/devices/cpm.h>
    10.9  
   10.10  #include <l4/sys/types.h>
   10.11  #include <stdint.h>
   10.12 @@ -133,9 +133,6 @@
   10.13    uint32_t get_cpu_frequency();
   10.14    uint32_t get_hclock0_frequency();
   10.15    uint32_t get_hclock2_frequency();
   10.16 -  uint32_t get_hdmi_frequency();
   10.17 -  uint32_t get_lcd_pixel_frequency(uint8_t controller);
   10.18 -  uint32_t get_lcd_pixel_frequency() { return get_lcd_pixel_frequency(0); }
   10.19    uint32_t get_memory_frequency();
   10.20    uint32_t get_pclock_frequency();
   10.21  
   10.22 @@ -144,11 +141,11 @@
   10.23    uint32_t get_mpll_frequency();
   10.24    uint32_t get_vpll_frequency();
   10.25  
   10.26 -  void set_hdmi_frequency(uint32_t pclk);
   10.27 -  void set_lcd_pixel_frequency(uint32_t pclk);
   10.28 -  void set_lcd_frequencies(uint32_t pclk, uint8_t multiplier);
   10.29    void set_pll_parameters(uint32_t pll_reg, uint16_t multiplier, uint8_t in_divider, uint8_t out_divider);
   10.30  
   10.31 +  uint32_t get_frequency(enum Clock_frequency_identifiers clock);
   10.32 +  void set_frequency(enum Clock_frequency_identifiers clock, uint32_t frequency);
   10.33 +
   10.34    void update_output_frequency();
   10.35  };
   10.36  
   10.37 @@ -196,8 +193,6 @@
   10.38  uint32_t jz4780_cpm_get_cpu_frequency(void *cpm);
   10.39  uint32_t jz4780_cpm_get_hclock0_frequency(void *cpm);
   10.40  uint32_t jz4780_cpm_get_hclock2_frequency(void *cpm);
   10.41 -uint32_t jz4780_cpm_get_hdmi_frequency(void *cpm);
   10.42 -uint32_t jz4780_cpm_get_lcd_pixel_frequency(void *cpm);
   10.43  uint32_t jz4780_cpm_get_memory_frequency(void *cpm);
   10.44  uint32_t jz4780_cpm_get_pclock_frequency(void *cpm);
   10.45  
   10.46 @@ -206,9 +201,9 @@
   10.47  uint32_t jz4780_cpm_get_mpll_frequency(void *cpm);
   10.48  uint32_t jz4780_cpm_get_vpll_frequency(void *cpm);
   10.49  
   10.50 -void jz4780_cpm_set_hdmi_frequency(void *cpm, uint32_t pclk);
   10.51 -void jz4780_cpm_set_lcd_pixel_frequency(void *cpm, uint32_t pclk);
   10.52 -void jz4780_cpm_set_lcd_frequencies(void *cpm, uint32_t pclk, uint8_t ratio);
   10.53 +uint32_t jz4780_cpm_get_frequency(void *cpm, enum Clock_frequency_identifiers clock);
   10.54 +void jz4780_cpm_set_frequency(void *cpm, enum Clock_frequency_identifiers clock, uint32_t frequency);
   10.55 +
   10.56  void jz4780_cpm_set_mpll_parameters(void *cpm, uint16_t multiplier, uint8_t in_divider, uint8_t out_divider);
   10.57  
   10.58  EXTERN_C_END
    11.1 --- a/pkg/devices/lib/cpm/include/cpm.h	Sat Jan 30 23:39:17 2021 +0100
    11.2 +++ b/pkg/devices/lib/cpm/include/cpm.h	Sun Jan 31 00:49:22 2021 +0100
    11.3 @@ -34,12 +34,6 @@
    11.4  class Cpm_chip
    11.5  {
    11.6  public:
    11.7 -  virtual uint32_t get_lcd_pixel_frequency() = 0;
    11.8 -
    11.9 -  virtual void set_hdmi_frequency(uint32_t) { }
   11.10 -
   11.11 -  virtual void set_lcd_frequencies(uint32_t pclk, uint8_t ratio) = 0;
   11.12 -
   11.13    virtual int have_clock(enum Clock_identifiers clock) = 0;
   11.14  
   11.15    virtual void start_clock(enum Clock_identifiers clock) = 0;
    12.1 --- a/pkg/devices/lib/cpm/src/jz4730.cc	Sat Jan 30 23:39:17 2021 +0100
    12.2 +++ b/pkg/devices/lib/cpm/src/jz4730.cc	Sun Jan 31 00:49:22 2021 +0100
    12.3 @@ -3,7 +3,7 @@
    12.4   * provided by the jz4730. The power management functionality could be exposed
    12.5   * using a separate driver.
    12.6   *
    12.7 - * Copyright (C) 2017, 2018, 2020 Paul Boddie <paul@boddie.org.uk>
    12.8 + * Copyright (C) 2017, 2018, 2020, 2021 Paul Boddie <paul@boddie.org.uk>
    12.9   *
   12.10   * This program is free software; you can redistribute it and/or
   12.11   * modify it under the terms of the GNU General Public License as
   12.12 @@ -299,27 +299,37 @@
   12.13  
   12.14  
   12.15  uint32_t
   12.16 -Cpm_jz4730_chip::get_lcd_pixel_frequency()
   12.17 +Cpm_jz4730_chip::get_frequency(enum Clock_frequency_identifiers clock)
   12.18  {
   12.19 -  return get_output_frequency() / get_lcd_pixel_divider();
   12.20 +  if (clock == Clock_frequency_lcd_pixel)
   12.21 +    return get_output_frequency() / get_lcd_pixel_divider();
   12.22 +
   12.23 +  // NOTE: Consider a better error result.
   12.24 +  return 0;
   12.25  }
   12.26  
   12.27 -// Set the device and pixel frequencies, indicating the latter and
   12.28 -// providing the device:pixel frequency ratio.
   12.29 -
   12.30  void
   12.31 -Cpm_jz4730_chip::set_lcd_frequencies(uint32_t pclk, uint8_t ratio)
   12.32 +Cpm_jz4730_chip::set_frequency(enum Clock_frequency_identifiers clock, uint32_t frequency)
   12.33  {
   12.34 -  uint32_t out = get_output_frequency(),
   12.35 -           lcd = pclk * ratio;
   12.36 +  uint32_t out = get_output_frequency();
   12.37 +
   12.38 +  switch (clock)
   12.39 +  {
   12.40 +    // Limit the device frequency to 150MHz.
   12.41  
   12.42 -  set_lcd_pixel_divider(out / pclk);
   12.43 -
   12.44 -  // Limit the device frequency to 150MHz.
   12.45 +    case Clock_frequency_lcd:
   12.46 +      if (frequency > 150000000)
   12.47 +        frequency = 150000000;
   12.48 +      set_lcd_device_divider(out / frequency);
   12.49 +      break;
   12.50  
   12.51 -  if (lcd > 150000000) lcd = 150000000;
   12.52 +    case Clock_frequency_lcd_pixel:
   12.53 +      set_lcd_pixel_divider(out / frequency);
   12.54 +      break;
   12.55  
   12.56 -  set_lcd_device_divider(out / lcd);
   12.57 +    default:
   12.58 +      break;
   12.59 +  }
   12.60  }
   12.61  
   12.62  
   12.63 @@ -461,15 +471,15 @@
   12.64  }
   12.65  
   12.66  uint32_t
   12.67 -jz4730_cpm_get_lcd_pixel_frequency(void *cpm)
   12.68 +jz4730_cpm_get_frequency(void *cpm, enum Clock_frequency_identifiers clock)
   12.69  {
   12.70 -  return static_cast<Cpm_jz4730_chip *>(cpm)->get_lcd_pixel_frequency();
   12.71 +  return static_cast<Cpm_jz4730_chip *>(cpm)->get_frequency(clock);
   12.72  }
   12.73  
   12.74  void
   12.75 -jz4730_cpm_set_lcd_frequencies(void *cpm, uint32_t pclk, uint8_t ratio)
   12.76 +jz4730_cpm_set_frequency(void *cpm, enum Clock_frequency_identifiers clock, uint32_t frequency)
   12.77  {
   12.78 -  static_cast<Cpm_jz4730_chip *>(cpm)->set_lcd_frequencies(pclk, ratio);
   12.79 +  static_cast<Cpm_jz4730_chip *>(cpm)->set_frequency(clock, frequency);
   12.80  }
   12.81  
   12.82  void
    13.1 --- a/pkg/devices/lib/cpm/src/jz4740.cc	Sat Jan 30 23:39:17 2021 +0100
    13.2 +++ b/pkg/devices/lib/cpm/src/jz4740.cc	Sun Jan 31 00:49:22 2021 +0100
    13.3 @@ -252,28 +252,41 @@
    13.4  
    13.5  
    13.6  
    13.7 -uint32_t
    13.8 -Cpm_jz4740_chip::get_lcd_pixel_frequency()
    13.9 -{
   13.10 -  return get_output_frequency() / get_lcd_pixel_divider();
   13.11 -}
   13.12 -
   13.13  // Set the device and pixel frequencies, indicating the latter and
   13.14  // providing the device:pixel frequency ratio.
   13.15  
   13.16 -void
   13.17 -Cpm_jz4740_chip::set_lcd_frequencies(uint32_t pclk, uint8_t ratio)
   13.18 +uint32_t
   13.19 +Cpm_jz4740_chip::get_frequency(enum Clock_frequency_identifiers clock)
   13.20  {
   13.21 -  uint32_t out = get_output_frequency(),
   13.22 -           lcd = pclk * ratio;
   13.23 +  if (clock == Clock_frequency_lcd_pixel)
   13.24 +    return get_output_frequency() / get_lcd_pixel_divider();
   13.25 +
   13.26 +  // NOTE: Consider a better error result.
   13.27 +  return 0;
   13.28 +}
   13.29 +
   13.30 +void
   13.31 +Cpm_jz4740_chip::set_frequency(enum Clock_frequency_identifiers clock, uint32_t frequency)
   13.32 +{
   13.33 +  uint32_t out = get_output_frequency();
   13.34  
   13.35 -  set_lcd_pixel_divider(out / pclk);
   13.36 -
   13.37 -  // Limit the device frequency to 150MHz.
   13.38 +  switch (clock)
   13.39 +  {
   13.40 +    // Limit the device frequency to 150MHz.
   13.41  
   13.42 -  if (lcd > 150000000) lcd = 150000000;
   13.43 +    case Clock_frequency_lcd:
   13.44 +      if (frequency > 150000000)
   13.45 +        frequency = 150000000;
   13.46 +      set_lcd_device_divider(out / frequency);
   13.47 +      break;
   13.48  
   13.49 -  set_lcd_device_divider(out / lcd);
   13.50 +    case Clock_frequency_lcd_pixel:
   13.51 +      set_lcd_pixel_divider(out / frequency);
   13.52 +      break;
   13.53 +
   13.54 +    default:
   13.55 +      break;
   13.56 +  }
   13.57  }
   13.58  
   13.59  
   13.60 @@ -403,15 +416,15 @@
   13.61  }
   13.62  
   13.63  uint32_t
   13.64 -jz4740_cpm_get_lcd_pixel_frequency(void *cpm)
   13.65 +jz4740_cpm_get_frequency(void *cpm, enum Clock_frequency_identifiers clock)
   13.66  {
   13.67 -  return static_cast<Cpm_jz4740_chip *>(cpm)->get_lcd_pixel_frequency();
   13.68 +  return static_cast<Cpm_jz4740_chip *>(cpm)->get_frequency(clock);
   13.69  }
   13.70  
   13.71  void
   13.72 -jz4740_cpm_set_lcd_frequencies(void *cpm, uint32_t pclk, uint8_t ratio)
   13.73 +jz4740_cpm_set_frequency(void *cpm, enum Clock_frequency_identifiers clock, uint32_t frequency)
   13.74  {
   13.75 -  static_cast<Cpm_jz4740_chip *>(cpm)->set_lcd_frequencies(pclk, ratio);
   13.76 +  static_cast<Cpm_jz4740_chip *>(cpm)->set_frequency(clock, frequency);
   13.77  }
   13.78  
   13.79  void
    14.1 --- a/pkg/devices/lib/cpm/src/jz4780.cc	Sat Jan 30 23:39:17 2021 +0100
    14.2 +++ b/pkg/devices/lib/cpm/src/jz4780.cc	Sun Jan 31 00:49:22 2021 +0100
    14.3 @@ -3,7 +3,7 @@
    14.4   * provided by the jz4780 and related SoCs. The power management
    14.5   * functionality could be exposed using a separate driver.
    14.6   *
    14.7 - * Copyright (C) 2017, 2018, 2020 Paul Boddie <paul@boddie.org.uk>
    14.8 + * Copyright (C) 2017, 2018, 2020, 2021 Paul Boddie <paul@boddie.org.uk>
    14.9   *
   14.10   * This program is free software; you can redistribute it and/or
   14.11   * modify it under the terms of the GNU General Public License as
   14.12 @@ -472,11 +472,11 @@
   14.13    switch (get_memory_source())
   14.14    {
   14.15      case Source_mux_main:
   14.16 -    return get_main_frequency();
   14.17 +      return get_main_frequency();
   14.18      case Source_mux_pll_M:
   14.19 -    return get_pll_frequency(Pll_control_M);
   14.20 +      return get_pll_frequency(Pll_control_M);
   14.21      default:
   14.22 -    return 0;
   14.23 +      return 0;
   14.24    }
   14.25  }
   14.26  
   14.27 @@ -492,13 +492,13 @@
   14.28    switch (get_cpu_source())
   14.29    {
   14.30      case Source_mux_main:
   14.31 -    return get_main_frequency();
   14.32 +      return get_main_frequency();
   14.33      case Source_mux_pll_M:
   14.34 -    return get_pll_frequency(Pll_control_M);
   14.35 +      return get_pll_frequency(Pll_control_M);
   14.36      case Source_mux_pll_E:
   14.37 -    return get_pll_frequency(Pll_control_E);
   14.38 +      return get_pll_frequency(Pll_control_E);
   14.39      default:
   14.40 -    return 0;
   14.41 +      return 0;
   14.42    }
   14.43  }
   14.44  
   14.45 @@ -514,13 +514,13 @@
   14.46    switch (get_hclock0_source())
   14.47    {
   14.48      case Source_mux_main:
   14.49 -    return get_main_frequency();
   14.50 +      return get_main_frequency();
   14.51      case Source_mux_pll_M:
   14.52 -    return get_pll_frequency(Pll_control_M);
   14.53 +      return get_pll_frequency(Pll_control_M);
   14.54      case Source_mux_pll_E:
   14.55 -    return get_pll_frequency(Pll_control_E);
   14.56 +      return get_pll_frequency(Pll_control_E);
   14.57      default:
   14.58 -    return 0;
   14.59 +      return 0;
   14.60    }
   14.61  }
   14.62  
   14.63 @@ -536,13 +536,13 @@
   14.64    switch (get_hclock2_source())
   14.65    {
   14.66      case Source_mux_main:
   14.67 -    return get_main_frequency();
   14.68 +      return get_main_frequency();
   14.69      case Source_mux_pll_M:
   14.70 -    return get_pll_frequency(Pll_control_M);
   14.71 +      return get_pll_frequency(Pll_control_M);
   14.72      case Source_mux_realtime:
   14.73 -    return _rtclk_freq; // "TCK" in the manual, RTCLK in Linux driver code
   14.74 +      return _rtclk_freq; // "TCK" in the manual, RTCLK in Linux driver code
   14.75      default:
   14.76 -    return 0;
   14.77 +      return 0;
   14.78    }
   14.79  }
   14.80  
   14.81 @@ -564,13 +564,13 @@
   14.82    switch (get_hdmi_source())
   14.83    {
   14.84      case Source_main:
   14.85 -    return get_main_frequency();
   14.86 +      return get_main_frequency();
   14.87      case Source_pll_M:
   14.88 -    return get_pll_frequency(Pll_control_M);
   14.89 +      return get_pll_frequency(Pll_control_M);
   14.90      case Source_pll_V:
   14.91 -    return get_pll_frequency(Pll_control_V);
   14.92 +      return get_pll_frequency(Pll_control_V);
   14.93      default:
   14.94 -    return 0;
   14.95 +      return 0;
   14.96    }
   14.97  }
   14.98  
   14.99 @@ -603,13 +603,13 @@
  14.100    switch (get_lcd_source(controller))
  14.101    {
  14.102      case Source_main:
  14.103 -    return get_main_frequency();
  14.104 +      return get_main_frequency();
  14.105      case Source_pll_M:
  14.106 -    return get_pll_frequency(Pll_control_M);
  14.107 +      return get_pll_frequency(Pll_control_M);
  14.108      case Source_pll_V:
  14.109 -    return get_pll_frequency(Pll_control_V);
  14.110 +      return get_pll_frequency(Pll_control_V);
  14.111      default:
  14.112 -    return 0;
  14.113 +      return 0;
  14.114    }
  14.115  }
  14.116  
  14.117 @@ -666,13 +666,13 @@
  14.118    switch (get_main_source())
  14.119    {
  14.120      case Source_pll_A:
  14.121 -    return get_pll_frequency(Pll_control_A);
  14.122 +      return get_pll_frequency(Pll_control_A);
  14.123      case Source_external:
  14.124 -    return _exclk_freq;
  14.125 +      return _exclk_freq;
  14.126      case Source_realtime:
  14.127 -    return _rtclk_freq;
  14.128 +      return _rtclk_freq;
  14.129      default:
  14.130 -    return 0;
  14.131 +      return 0;
  14.132    }
  14.133  }
  14.134  
  14.135 @@ -708,22 +708,6 @@
  14.136    return get_pclock_source_frequency() / get_pclock_divider();
  14.137  }
  14.138  
  14.139 -// Clock frequency for the HDMI peripheral.
  14.140 -
  14.141 -uint32_t
  14.142 -Cpm_jz4780_chip::get_hdmi_frequency()
  14.143 -{
  14.144 -  return get_hdmi_source_frequency() / get_hdmi_divider();
  14.145 -}
  14.146 -
  14.147 -// Clock frequency for the LCD0 or LCD1 controller.
  14.148 -
  14.149 -uint32_t
  14.150 -Cpm_jz4780_chip::get_lcd_pixel_frequency(uint8_t controller)
  14.151 -{
  14.152 -  return get_lcd_source_frequency(controller) / get_lcd_pixel_divider(controller);
  14.153 -}
  14.154 -
  14.155  // Clock frequency for the memory.
  14.156  
  14.157  uint32_t
  14.158 @@ -758,44 +742,67 @@
  14.159  
  14.160  
  14.161  
  14.162 -void
  14.163 -Cpm_jz4780_chip::set_hdmi_frequency(uint32_t pclk)
  14.164 +uint32_t
  14.165 +Cpm_jz4780_chip::get_frequency(enum Clock_frequency_identifiers clock)
  14.166  {
  14.167 -  // Switch to the video PLL and attempt to set the divider.
  14.168 +  switch (clock)
  14.169 +  {
  14.170 +    // NOTE: Returning only the frequency for controller 0.
  14.171 +
  14.172 +    case Clock_frequency_lcd_pixel:
  14.173 +      return get_lcd_source_frequency(0) / get_lcd_pixel_divider(0);
  14.174  
  14.175 -  set_hdmi_source(Source_pll_V);
  14.176 -  pll_enable(Pll_control_V);
  14.177 -  set_hdmi_divider(get_hdmi_source_frequency() / pclk);
  14.178 +    case Clock_frequency_hdmi:
  14.179 +      return get_hdmi_source_frequency() / get_hdmi_divider();
  14.180 +
  14.181 +    // NOTE: Consider a better error result.
  14.182 +
  14.183 +    default:
  14.184 +      return 0;
  14.185 +  }
  14.186  }
  14.187  
  14.188 -// Set the pixel frequency.
  14.189 -// Unlike the jz4740, HCLK/AHB0 is used as the device frequency, with the pixel
  14.190 -// frequency being based on the selected clock source (SCLK_A, MPLL or VPLL).
  14.191 -
  14.192  void
  14.193 -Cpm_jz4780_chip::set_lcd_pixel_frequency(uint32_t pclk)
  14.194 +Cpm_jz4780_chip::set_frequency(enum Clock_frequency_identifiers clock, uint32_t frequency)
  14.195  {
  14.196 -  // Switch to the video PLL and attempt to set the divider.
  14.197 +  switch (clock)
  14.198 +  {
  14.199 +    // NOTE: HCLK/AHB0 must be 1.5 (for TFT) or 3 (for STN) times the pixel clock.
  14.200 +    // NOTE: Here, the actual frequency value is ignored, but should at least be
  14.201 +    // NOTE: tested.
  14.202 +
  14.203 +    case Clock_frequency_lcd:
  14.204 +      set_lcd_source(0, Source_pll_V);
  14.205 +      set_lcd_source(1, Source_pll_V);
  14.206 +      pll_enable(Pll_control_V);
  14.207 +      break;
  14.208 +
  14.209 +    // Unlike the JZ4740, HCLK/AHB0 is used as the device frequency, with the pixel
  14.210 +    // frequency being based on the selected clock source (SCLK_A, MPLL or VPLL).
  14.211 +
  14.212 +    case Clock_frequency_lcd_pixel:
  14.213  
  14.214 -  set_lcd_source(0, Source_pll_V);
  14.215 -  set_lcd_source(1, Source_pll_V);
  14.216 -  pll_enable(Pll_control_V);
  14.217 -  set_lcd_pixel_divider(0, get_lcd_source_frequency() / pclk);
  14.218 -  set_lcd_pixel_divider(1, get_lcd_source_frequency() / pclk);
  14.219 -}
  14.220 +      // Switch to the video PLL and attempt to set the divider.
  14.221 +
  14.222 +      set_lcd_pixel_divider(0, get_lcd_source_frequency() / frequency);
  14.223 +      set_lcd_pixel_divider(1, get_lcd_source_frequency() / frequency);
  14.224 +      break;
  14.225 +
  14.226 +    case Clock_frequency_hdmi:
  14.227  
  14.228 -// NOTE: Compatibility method. Probably needs reviewing.
  14.229 -// NOTE: HCLK/AHB0 must be 1.5 (for TFT) or 3 (for STN) times the pixel clock.
  14.230 +      // Switch to the video PLL and attempt to set the divider.
  14.231  
  14.232 -void
  14.233 -Cpm_jz4780_chip::set_lcd_frequencies(uint32_t pclk, uint8_t ratio)
  14.234 -{
  14.235 -  (void) ratio;
  14.236 -  set_lcd_pixel_frequency(pclk);
  14.237 +      set_hdmi_source(Source_pll_V);
  14.238 +      pll_enable(Pll_control_V);
  14.239 +      set_hdmi_divider(get_hdmi_source_frequency() / frequency);
  14.240 +      break;
  14.241 +
  14.242 +    default:
  14.243 +      break;
  14.244 +  }
  14.245  }
  14.246  
  14.247  // NOTE: Empty method for compatibility.
  14.248 -// NOTE: It could potentially be combined with start_lcd.
  14.249  
  14.250  void
  14.251  Cpm_jz4780_chip::update_output_frequency()
  14.252 @@ -992,18 +999,6 @@
  14.253  }
  14.254  
  14.255  uint32_t
  14.256 -jz4780_cpm_get_hdmi_frequency(void *cpm)
  14.257 -{
  14.258 -  return static_cast<Cpm_jz4780_chip *>(cpm)->get_hdmi_frequency();
  14.259 -}
  14.260 -
  14.261 -uint32_t
  14.262 -jz4780_cpm_get_lcd_pixel_frequency(void *cpm)
  14.263 -{
  14.264 -  return static_cast<Cpm_jz4780_chip *>(cpm)->get_lcd_pixel_frequency();
  14.265 -}
  14.266 -
  14.267 -uint32_t
  14.268  jz4780_cpm_get_memory_frequency(void *cpm)
  14.269  {
  14.270    return static_cast<Cpm_jz4780_chip *>(cpm)->get_memory_frequency();
  14.271 @@ -1041,22 +1036,16 @@
  14.272  
  14.273  
  14.274  
  14.275 -void
  14.276 -jz4780_cpm_set_hdmi_frequency(void *cpm, uint32_t pclk)
  14.277 +uint32_t
  14.278 +jz4780_cpm_get_frequency(void *cpm, enum Clock_frequency_identifiers clock)
  14.279  {
  14.280 -  static_cast<Cpm_jz4780_chip *>(cpm)->set_hdmi_frequency(pclk);
  14.281 +  return static_cast<Cpm_jz4780_chip *>(cpm)->get_frequency(clock);
  14.282  }
  14.283  
  14.284  void
  14.285 -jz4780_cpm_set_lcd_pixel_frequency(void *cpm, uint32_t pclk)
  14.286 +jz4780_cpm_set_frequency(void *cpm, enum Clock_frequency_identifiers clock, uint32_t frequency)
  14.287  {
  14.288 -  static_cast<Cpm_jz4780_chip *>(cpm)->set_lcd_pixel_frequency(pclk);
  14.289 -}
  14.290 -
  14.291 -void
  14.292 -jz4780_cpm_set_lcd_frequencies(void *cpm, uint32_t pclk, uint8_t ratio)
  14.293 -{
  14.294 -  static_cast<Cpm_jz4780_chip *>(cpm)->set_lcd_frequencies(pclk, ratio);
  14.295 +  static_cast<Cpm_jz4780_chip *>(cpm)->set_frequency(clock, frequency);
  14.296  }
  14.297  
  14.298  void
    15.1 --- a/pkg/landfall-examples/ci20_cpm/ci20_cpm.c	Sat Jan 30 23:39:17 2021 +0100
    15.2 +++ b/pkg/landfall-examples/ci20_cpm/ci20_cpm.c	Sun Jan 31 00:49:22 2021 +0100
    15.3 @@ -1,7 +1,7 @@
    15.4  /*
    15.5   * (c) 2008-2009 Adam Lackorzynski <adam@os.inf.tu-dresden.de>
    15.6   *     economic rights: Technische Universität Dresden (Germany)
    15.7 - * Copyright (C) 2017, 2018 Paul Boddie <paul@boddie.org.uk>
    15.8 + * Copyright (C) 2017, 2018, 2021 Paul Boddie <paul@boddie.org.uk>
    15.9   *
   15.10   * This file is part of TUD:OS and distributed under the terms of the
   15.11   * GNU General Public License 2.
   15.12 @@ -156,16 +156,16 @@
   15.13    printf("LCD source: %d\n", jz4780_cpm_get_lcd_source(cpm));
   15.14    printf("  LCD source frequency: %d\n", jz4780_cpm_get_lcd_source_frequency(cpm));
   15.15    printf("  LCD pixel clock divider: %d\n", jz4780_cpm_get_lcd_pixel_divider(cpm));
   15.16 -  printf("  LCD pixel clock frequency: %d\n", jz4780_cpm_get_lcd_pixel_frequency(cpm));
   15.17 +  printf("  LCD pixel clock frequency: %d\n", jz4780_cpm_get_frequency(cpm, Clock_frequency_lcd_pixel));
   15.18  
   15.19    /* Attempt to set the pixel clock frequency. */
   15.20  
   15.21 -  jz4780_cpm_set_lcd_pixel_frequency(cpm, 108000000);
   15.22 +  jz4780_cpm_set_frequency(cpm, Clock_frequency_lcd_pixel, 108000000);
   15.23  
   15.24    printf("LCD source: %d\n", jz4780_cpm_get_lcd_source(cpm));
   15.25    printf("  LCD source frequency: %d\n", jz4780_cpm_get_lcd_source_frequency(cpm));
   15.26    printf("  LCD pixel clock divider: %d\n", jz4780_cpm_get_lcd_pixel_divider(cpm));
   15.27 -  printf("  LCD pixel clock frequency: %d\n", jz4780_cpm_get_lcd_pixel_frequency(cpm));
   15.28 +  printf("  LCD pixel clock frequency: %d\n", jz4780_cpm_get_frequency(cpm, Clock_frequency_lcd_pixel));
   15.29  
   15.30    /* Attempt to set the peripheral clock frequency. */
   15.31  
    16.1 --- a/pkg/landfall-examples/ci20_hdmi_i2c/ci20_hdmi_i2c.c	Sat Jan 30 23:39:17 2021 +0100
    16.2 +++ b/pkg/landfall-examples/ci20_hdmi_i2c/ci20_hdmi_i2c.c	Sun Jan 31 00:49:22 2021 +0100
    16.3 @@ -1,7 +1,7 @@
    16.4  /*
    16.5   * Access the HDMI I2C peripheral on the MIPS Creator CI20 board.
    16.6   *
    16.7 - * Copyright (C) 2020 Paul Boddie <paul@boddie.org.uk>
    16.8 + * Copyright (C) 2020, 2021 Paul Boddie <paul@boddie.org.uk>
    16.9   *
   16.10   * This program is free software; you can redistribute it and/or
   16.11   * modify it under the terms of the GNU General Public License as
   16.12 @@ -268,15 +268,15 @@
   16.13  
   16.14    printf("VPLL frequency: %d\n", jz4780_cpm_get_vpll_frequency(cpm));
   16.15    printf("HDMI divider: %d\n", jz4780_cpm_get_hdmi_divider(cpm));
   16.16 -  printf("HDMI frequency: %d\n", jz4780_cpm_get_hdmi_frequency(cpm));
   16.17 +  printf("HDMI frequency: %d\n", jz4780_cpm_get_frequency(cpm, Clock_frequency_hdmi));
   16.18  
   16.19 -  jz4780_cpm_stop_hdmi(cpm);
   16.20 -  jz4780_cpm_set_hdmi_frequency(cpm, 27000000);
   16.21 +  jz4780_cpm_stop_clock(cpm, Clock_hdmi);
   16.22 +  jz4780_cpm_set_frequency(cpm, Clock_frequency_hdmi, 27000000);
   16.23  
   16.24    printf("HDMI divider: %d\n", jz4780_cpm_get_hdmi_divider(cpm));
   16.25 -  printf("HDMI frequency: %d\n", jz4780_cpm_get_hdmi_frequency(cpm));
   16.26 +  printf("HDMI frequency: %d\n", jz4780_cpm_get_frequency(cpm, Clock_frequency_hdmi));
   16.27  
   16.28 -  jz4780_cpm_start_hdmi(cpm);
   16.29 +  jz4780_cpm_start_clock(cpm, Clock_hdmi);
   16.30  
   16.31    /* Configure pins. */
   16.32  
   16.33 @@ -336,22 +336,22 @@
   16.34  
   16.35    printf("LCD source: %d\n", jz4780_cpm_get_lcd_source(cpm));
   16.36    printf("LCD divider: %d\n", jz4780_cpm_get_lcd_pixel_divider(cpm));
   16.37 -  printf("LCD frequency: %d\n", jz4780_cpm_get_lcd_pixel_frequency(cpm));
   16.38 +  printf("LCD frequency: %d\n", jz4780_cpm_get_frequency(cpm, Clock_frequency_lcd_pixel));
   16.39    printf("Desired frequency: %d\n", jz4740_lcd_get_pixel_clock(lcd));
   16.40  
   16.41 -  jz4780_cpm_stop_lcd(cpm);
   16.42 -  jz4780_cpm_set_lcd_frequencies(cpm, jz4740_lcd_get_pixel_clock(lcd), 3);
   16.43 +  jz4780_cpm_stop_clock(cpm, Clock_lcd);
   16.44 +  jz4780_cpm_set_frequency(cpm, Clock_frequency_lcd_pixel, jz4740_lcd_get_pixel_clock(lcd));
   16.45  
   16.46    printf("LCD source: %d\n", jz4780_cpm_get_lcd_source(cpm));
   16.47    printf("LCD divider: %d\n", jz4780_cpm_get_lcd_pixel_divider(cpm));
   16.48 -  printf("LCD frequency: %d\n", jz4780_cpm_get_lcd_pixel_frequency(cpm));
   16.49 +  printf("LCD frequency: %d\n", jz4780_cpm_get_frequency(cpm, Clock_frequency_lcd_pixel));
   16.50    printf("AHB0 frequency: %d\n", jz4780_cpm_get_hclock0_frequency(cpm));
   16.51  
   16.52    /* With the LCD pixel clock set up, bring up the HDMI. */
   16.53  
   16.54    printf("Enable HDMI output...\n");
   16.55  
   16.56 -  jz4780_hdmi_enable(hdmi, jz4780_cpm_get_lcd_pixel_frequency(cpm));
   16.57 +  jz4780_hdmi_enable(hdmi, jz4780_cpm_get_frequency(cpm, Clock_frequency_lcd_pixel));
   16.58  
   16.59    /* Allocate descriptors and framebuffer at 2**8 == 256 byte == 64 word alignment. */
   16.60  
   16.61 @@ -417,7 +417,7 @@
   16.62  
   16.63    printf("Start LCD clock and initialise LCD...\n");
   16.64  
   16.65 -  jz4780_cpm_start_lcd(cpm);
   16.66 +  jz4780_cpm_start_clock(cpm, Clock_lcd);
   16.67    l4_sleep(1); // 1ms == 1000us
   16.68  
   16.69    jz4740_lcd_disable(lcd);