# HG changeset patch # User Paul Boddie # Date 1612050562 -3600 # Node ID 64fb2fa9968068ec07b85e54366f6ba33f68070c # Parent 686488c38e1d423caef4e5b672fe94f19d8358f3 Introduced generic clock frequency control methods to the CPM library and device, used by the LCD and HDMI devices and some examples. diff -r 686488c38e1d -r 64fb2fa99680 pkg/devices/cpm/src/jz4730/cpm-jz4730.cc --- a/pkg/devices/cpm/src/jz4730/cpm-jz4730.cc Sat Jan 30 23:39:17 2021 +0100 +++ b/pkg/devices/cpm/src/jz4730/cpm-jz4730.cc Sun Jan 31 00:49:22 2021 +0100 @@ -57,9 +57,9 @@ { } - long set_lcd_frequencies(uint32_t pclk, uint8_t multiplier) + long set_frequency(enum Clock_frequency_identifiers clock, uint32_t frequency) { - _chip->set_lcd_frequencies(pclk, multiplier); + _chip->set_frequency(clock, frequency); return L4_EOK; } diff -r 686488c38e1d -r 64fb2fa99680 pkg/devices/cpm/src/jz4740/cpm-jz4740.cc --- a/pkg/devices/cpm/src/jz4740/cpm-jz4740.cc Sat Jan 30 23:39:17 2021 +0100 +++ b/pkg/devices/cpm/src/jz4740/cpm-jz4740.cc Sun Jan 31 00:49:22 2021 +0100 @@ -57,9 +57,9 @@ { } - long set_lcd_frequencies(uint32_t pclk, uint8_t multiplier) + long set_frequency(enum Clock_frequency_identifiers clock, uint32_t frequency) { - _chip->set_lcd_frequencies(pclk, multiplier); + _chip->set_frequency(clock, frequency); return L4_EOK; } diff -r 686488c38e1d -r 64fb2fa99680 pkg/devices/cpm/src/jz4780/cpm-jz4780.cc --- a/pkg/devices/cpm/src/jz4780/cpm-jz4780.cc Sat Jan 30 23:39:17 2021 +0100 +++ b/pkg/devices/cpm/src/jz4780/cpm-jz4780.cc Sun Jan 31 00:49:22 2021 +0100 @@ -57,21 +57,15 @@ { } - long get_lcd_pixel_frequency(uint8_t controller, uint32_t *frequency) + long get_frequency(enum Clock_frequency_identifiers clock, uint32_t *frequency) { - *frequency = _chip->get_lcd_pixel_frequency(controller); + *frequency = _chip->get_frequency(clock); return L4_EOK; } - long set_hdmi_frequency(uint32_t frequency) + long set_frequency(enum Clock_frequency_identifiers clock, uint32_t frequency) { - _chip->set_hdmi_frequency(frequency); - return L4_EOK; - } - - long set_lcd_frequencies(uint32_t pclk, uint8_t multiplier) - { - _chip->set_lcd_frequencies(pclk, multiplier); + _chip->set_frequency(clock, frequency); return L4_EOK; } diff -r 686488c38e1d -r 64fb2fa99680 pkg/devices/display/src/ci20/display-ci20_hdmi.cc --- a/pkg/devices/display/src/ci20/display-ci20_hdmi.cc Sat Jan 30 23:39:17 2021 +0100 +++ b/pkg/devices/display/src/ci20/display-ci20_hdmi.cc Sun Jan 31 00:49:22 2021 +0100 @@ -1,7 +1,7 @@ /* * Export MIPS Creator CI20 HDMI display operations as a server. * - * Copyright (C) 2018, 2020 Paul Boddie + * Copyright (C) 2018, 2020, 2021 Paul Boddie * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as @@ -65,7 +65,7 @@ /* Start the HDMI peripheral. */ cpm_device->stop_clock(Clock_hdmi); - cpm_device->set_hdmi_frequency(27000000); + cpm_device->set_frequency(Clock_frequency_hdmi, 27000000); cpm_device->start_clock(Clock_hdmi); /* Load the panel data from the configured library. */ @@ -119,7 +119,7 @@ // NOTE: Should test to see if it is connected. - if (!cpm_device->get_lcd_pixel_frequency(0, &frequency)) + if (!cpm_device->get_frequency(Clock_frequency_lcd_pixel, &frequency)) { hdmi->enable(frequency); } diff -r 686488c38e1d -r 64fb2fa99680 pkg/devices/idl/cpm.idl --- a/pkg/devices/idl/cpm.idl Sat Jan 30 23:39:17 2021 +0100 +++ b/pkg/devices/idl/cpm.idl Sun Jan 31 00:49:22 2021 +0100 @@ -8,11 +8,9 @@ [protocol(LANDFALL_CPM)] interface CPM { - void get_lcd_pixel_frequency(in uint8_t controller, out uint32_t frequency); + void get_frequency(in enum Clock_frequency_identifiers clock, out uint32_t frequency); - void set_hdmi_frequency(in uint32_t frequency); - - void set_lcd_frequencies(in uint32_t pclk, in uint8_t multiplier); + void set_frequency(in enum Clock_frequency_identifiers clock, in uint32_t frequency); void have_clock(in enum Clock_identifiers clock, out int enabled); diff -r 686488c38e1d -r 64fb2fa99680 pkg/devices/include/clocks.h --- a/pkg/devices/include/clocks.h Sat Jan 30 23:39:17 2021 +0100 +++ b/pkg/devices/include/clocks.h Sun Jan 31 00:49:22 2021 +0100 @@ -21,6 +21,10 @@ #pragma once +/* Identifiers for controllable "logical" or "abstract" clocks. Operations + involving these clocks may operate on multiple "physical" or "specific" + clocks. */ + enum Clock_identifiers { Clock_aic_bitclk, @@ -52,4 +56,13 @@ Clock_uprt, }; +/* Identifiers for clocks whose frequencies can be adjusted or inspected. */ + +enum Clock_frequency_identifiers +{ + Clock_frequency_lcd, + Clock_frequency_lcd_pixel, + Clock_frequency_hdmi, +}; + // vim: tabstop=2 expandtab shiftwidth=2 diff -r 686488c38e1d -r 64fb2fa99680 pkg/devices/lcd/src/jz4740/lcd-jz4740-device.cc --- a/pkg/devices/lcd/src/jz4740/lcd-jz4740-device.cc Sat Jan 30 23:39:17 2021 +0100 +++ b/pkg/devices/lcd/src/jz4740/lcd-jz4740-device.cc Sun Jan 31 00:49:22 2021 +0100 @@ -64,7 +64,8 @@ // 1.5 times that of the pixel clock, and a STN panel needs a device clock 3 // times that of the pixel clock. - cpm_device->set_lcd_frequencies(pclk, 3); + cpm_device->set_frequency(Clock_frequency_lcd, pclk * 3); + cpm_device->set_frequency(Clock_frequency_lcd_pixel, pclk); cpm_device->update_output_frequency(); cpm_device->start_clock(Clock_lcd); diff -r 686488c38e1d -r 64fb2fa99680 pkg/devices/lib/cpm/include/cpm-jz4730.h --- a/pkg/devices/lib/cpm/include/cpm-jz4730.h Sat Jan 30 23:39:17 2021 +0100 +++ b/pkg/devices/lib/cpm/include/cpm-jz4730.h Sun Jan 31 00:49:22 2021 +0100 @@ -21,7 +21,7 @@ #pragma once -#include "cpm.h" +#include #include #include @@ -66,11 +66,12 @@ uint8_t get_source_divider(); uint16_t get_lcd_pixel_divider(); - uint32_t get_lcd_pixel_frequency(); void set_lcd_device_divider(uint8_t division); void set_lcd_pixel_divider(uint16_t division); - void set_lcd_frequencies(uint32_t pclk, uint8_t ratio); + + uint32_t get_frequency(enum Clock_frequency_identifiers clock); + void set_frequency(enum Clock_frequency_identifiers clock, uint32_t frequency); int have_clock(enum Clock_identifiers clock); void start_clock(enum Clock_identifiers clock); @@ -103,9 +104,10 @@ void jz4730_cpm_stop_clock(void *cpm, enum Clock_identifiers clock); uint16_t jz4730_cpm_get_lcd_pixel_divider(void *cpm); -uint32_t jz4730_cpm_get_lcd_pixel_frequency(void *cpm); -void jz4730_cpm_set_lcd_frequencies(void *cpm, uint32_t pclk, uint8_t ratio); +uint32_t jz4730_cpm_get_frequency(void *cpm, enum Clock_frequency_identifiers clock); +void jz4730_cpm_set_frequency(void *cpm, enum Clock_frequency_identifiers clock, uint32_t frequency); + void jz4730_cpm_update_output_frequency(void *cpm); uint32_t jz4730_cpm_get_cpu_frequency(void *cpm); diff -r 686488c38e1d -r 64fb2fa99680 pkg/devices/lib/cpm/include/cpm-jz4740.h --- a/pkg/devices/lib/cpm/include/cpm-jz4740.h Sat Jan 30 23:39:17 2021 +0100 +++ b/pkg/devices/lib/cpm/include/cpm-jz4740.h Sun Jan 31 00:49:22 2021 +0100 @@ -21,7 +21,7 @@ #pragma once -#include "cpm.h" +#include #include #include @@ -70,11 +70,12 @@ uint8_t get_source_divider(); uint16_t get_lcd_pixel_divider(); - uint32_t get_lcd_pixel_frequency(); void set_lcd_device_divider(uint8_t division); void set_lcd_pixel_divider(uint16_t division); - void set_lcd_frequencies(uint32_t pclk, uint8_t ratio); + + uint32_t get_frequency(enum Clock_frequency_identifiers clock); + void set_frequency(enum Clock_frequency_identifiers clock, uint32_t frequency); uint32_t get_pll_frequency(); uint32_t get_output_frequency(); @@ -103,9 +104,10 @@ void jz4740_cpm_stop_clock(void *cpm, enum Clock_identifiers clock); uint16_t jz4740_cpm_get_lcd_pixel_divider(void *cpm); -uint32_t jz4740_cpm_get_lcd_pixel_frequency(void *cpm); -void jz4740_cpm_set_lcd_frequencies(void *cpm, uint32_t pclk, uint8_t ratio); +uint32_t jz4740_cpm_get_frequency(void *cpm, enum Clock_frequency_identifiers clock); +void jz4740_cpm_set_frequency(void *cpm, enum Clock_frequency_identifiers clock, uint32_t frequency); + void jz4740_cpm_update_output_frequency(void *cpm); uint32_t jz4740_cpm_get_cpu_frequency(void *cpm); diff -r 686488c38e1d -r 64fb2fa99680 pkg/devices/lib/cpm/include/cpm-jz4780.h --- a/pkg/devices/lib/cpm/include/cpm-jz4780.h Sat Jan 30 23:39:17 2021 +0100 +++ b/pkg/devices/lib/cpm/include/cpm-jz4780.h Sun Jan 31 00:49:22 2021 +0100 @@ -21,7 +21,7 @@ #pragma once -#include "cpm.h" +#include #include #include @@ -133,9 +133,6 @@ uint32_t get_cpu_frequency(); uint32_t get_hclock0_frequency(); uint32_t get_hclock2_frequency(); - uint32_t get_hdmi_frequency(); - uint32_t get_lcd_pixel_frequency(uint8_t controller); - uint32_t get_lcd_pixel_frequency() { return get_lcd_pixel_frequency(0); } uint32_t get_memory_frequency(); uint32_t get_pclock_frequency(); @@ -144,11 +141,11 @@ uint32_t get_mpll_frequency(); uint32_t get_vpll_frequency(); - void set_hdmi_frequency(uint32_t pclk); - void set_lcd_pixel_frequency(uint32_t pclk); - void set_lcd_frequencies(uint32_t pclk, uint8_t multiplier); void set_pll_parameters(uint32_t pll_reg, uint16_t multiplier, uint8_t in_divider, uint8_t out_divider); + uint32_t get_frequency(enum Clock_frequency_identifiers clock); + void set_frequency(enum Clock_frequency_identifiers clock, uint32_t frequency); + void update_output_frequency(); }; @@ -196,8 +193,6 @@ uint32_t jz4780_cpm_get_cpu_frequency(void *cpm); uint32_t jz4780_cpm_get_hclock0_frequency(void *cpm); uint32_t jz4780_cpm_get_hclock2_frequency(void *cpm); -uint32_t jz4780_cpm_get_hdmi_frequency(void *cpm); -uint32_t jz4780_cpm_get_lcd_pixel_frequency(void *cpm); uint32_t jz4780_cpm_get_memory_frequency(void *cpm); uint32_t jz4780_cpm_get_pclock_frequency(void *cpm); @@ -206,9 +201,9 @@ uint32_t jz4780_cpm_get_mpll_frequency(void *cpm); uint32_t jz4780_cpm_get_vpll_frequency(void *cpm); -void jz4780_cpm_set_hdmi_frequency(void *cpm, uint32_t pclk); -void jz4780_cpm_set_lcd_pixel_frequency(void *cpm, uint32_t pclk); -void jz4780_cpm_set_lcd_frequencies(void *cpm, uint32_t pclk, uint8_t ratio); +uint32_t jz4780_cpm_get_frequency(void *cpm, enum Clock_frequency_identifiers clock); +void jz4780_cpm_set_frequency(void *cpm, enum Clock_frequency_identifiers clock, uint32_t frequency); + void jz4780_cpm_set_mpll_parameters(void *cpm, uint16_t multiplier, uint8_t in_divider, uint8_t out_divider); EXTERN_C_END diff -r 686488c38e1d -r 64fb2fa99680 pkg/devices/lib/cpm/include/cpm.h --- a/pkg/devices/lib/cpm/include/cpm.h Sat Jan 30 23:39:17 2021 +0100 +++ b/pkg/devices/lib/cpm/include/cpm.h Sun Jan 31 00:49:22 2021 +0100 @@ -34,12 +34,6 @@ class Cpm_chip { public: - virtual uint32_t get_lcd_pixel_frequency() = 0; - - virtual void set_hdmi_frequency(uint32_t) { } - - virtual void set_lcd_frequencies(uint32_t pclk, uint8_t ratio) = 0; - virtual int have_clock(enum Clock_identifiers clock) = 0; virtual void start_clock(enum Clock_identifiers clock) = 0; diff -r 686488c38e1d -r 64fb2fa99680 pkg/devices/lib/cpm/src/jz4730.cc --- a/pkg/devices/lib/cpm/src/jz4730.cc Sat Jan 30 23:39:17 2021 +0100 +++ b/pkg/devices/lib/cpm/src/jz4730.cc Sun Jan 31 00:49:22 2021 +0100 @@ -3,7 +3,7 @@ * provided by the jz4730. The power management functionality could be exposed * using a separate driver. * - * Copyright (C) 2017, 2018, 2020 Paul Boddie + * Copyright (C) 2017, 2018, 2020, 2021 Paul Boddie * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as @@ -299,27 +299,37 @@ uint32_t -Cpm_jz4730_chip::get_lcd_pixel_frequency() +Cpm_jz4730_chip::get_frequency(enum Clock_frequency_identifiers clock) { - return get_output_frequency() / get_lcd_pixel_divider(); + if (clock == Clock_frequency_lcd_pixel) + return get_output_frequency() / get_lcd_pixel_divider(); + + // NOTE: Consider a better error result. + return 0; } -// Set the device and pixel frequencies, indicating the latter and -// providing the device:pixel frequency ratio. - void -Cpm_jz4730_chip::set_lcd_frequencies(uint32_t pclk, uint8_t ratio) +Cpm_jz4730_chip::set_frequency(enum Clock_frequency_identifiers clock, uint32_t frequency) { - uint32_t out = get_output_frequency(), - lcd = pclk * ratio; + uint32_t out = get_output_frequency(); + + switch (clock) + { + // Limit the device frequency to 150MHz. - set_lcd_pixel_divider(out / pclk); - - // Limit the device frequency to 150MHz. + case Clock_frequency_lcd: + if (frequency > 150000000) + frequency = 150000000; + set_lcd_device_divider(out / frequency); + break; - if (lcd > 150000000) lcd = 150000000; + case Clock_frequency_lcd_pixel: + set_lcd_pixel_divider(out / frequency); + break; - set_lcd_device_divider(out / lcd); + default: + break; + } } @@ -461,15 +471,15 @@ } uint32_t -jz4730_cpm_get_lcd_pixel_frequency(void *cpm) +jz4730_cpm_get_frequency(void *cpm, enum Clock_frequency_identifiers clock) { - return static_cast(cpm)->get_lcd_pixel_frequency(); + return static_cast(cpm)->get_frequency(clock); } void -jz4730_cpm_set_lcd_frequencies(void *cpm, uint32_t pclk, uint8_t ratio) +jz4730_cpm_set_frequency(void *cpm, enum Clock_frequency_identifiers clock, uint32_t frequency) { - static_cast(cpm)->set_lcd_frequencies(pclk, ratio); + static_cast(cpm)->set_frequency(clock, frequency); } void diff -r 686488c38e1d -r 64fb2fa99680 pkg/devices/lib/cpm/src/jz4740.cc --- a/pkg/devices/lib/cpm/src/jz4740.cc Sat Jan 30 23:39:17 2021 +0100 +++ b/pkg/devices/lib/cpm/src/jz4740.cc Sun Jan 31 00:49:22 2021 +0100 @@ -252,28 +252,41 @@ -uint32_t -Cpm_jz4740_chip::get_lcd_pixel_frequency() -{ - return get_output_frequency() / get_lcd_pixel_divider(); -} - // Set the device and pixel frequencies, indicating the latter and // providing the device:pixel frequency ratio. -void -Cpm_jz4740_chip::set_lcd_frequencies(uint32_t pclk, uint8_t ratio) +uint32_t +Cpm_jz4740_chip::get_frequency(enum Clock_frequency_identifiers clock) { - uint32_t out = get_output_frequency(), - lcd = pclk * ratio; + if (clock == Clock_frequency_lcd_pixel) + return get_output_frequency() / get_lcd_pixel_divider(); + + // NOTE: Consider a better error result. + return 0; +} + +void +Cpm_jz4740_chip::set_frequency(enum Clock_frequency_identifiers clock, uint32_t frequency) +{ + uint32_t out = get_output_frequency(); - set_lcd_pixel_divider(out / pclk); - - // Limit the device frequency to 150MHz. + switch (clock) + { + // Limit the device frequency to 150MHz. - if (lcd > 150000000) lcd = 150000000; + case Clock_frequency_lcd: + if (frequency > 150000000) + frequency = 150000000; + set_lcd_device_divider(out / frequency); + break; - set_lcd_device_divider(out / lcd); + case Clock_frequency_lcd_pixel: + set_lcd_pixel_divider(out / frequency); + break; + + default: + break; + } } @@ -403,15 +416,15 @@ } uint32_t -jz4740_cpm_get_lcd_pixel_frequency(void *cpm) +jz4740_cpm_get_frequency(void *cpm, enum Clock_frequency_identifiers clock) { - return static_cast(cpm)->get_lcd_pixel_frequency(); + return static_cast(cpm)->get_frequency(clock); } void -jz4740_cpm_set_lcd_frequencies(void *cpm, uint32_t pclk, uint8_t ratio) +jz4740_cpm_set_frequency(void *cpm, enum Clock_frequency_identifiers clock, uint32_t frequency) { - static_cast(cpm)->set_lcd_frequencies(pclk, ratio); + static_cast(cpm)->set_frequency(clock, frequency); } void diff -r 686488c38e1d -r 64fb2fa99680 pkg/devices/lib/cpm/src/jz4780.cc --- a/pkg/devices/lib/cpm/src/jz4780.cc Sat Jan 30 23:39:17 2021 +0100 +++ b/pkg/devices/lib/cpm/src/jz4780.cc Sun Jan 31 00:49:22 2021 +0100 @@ -3,7 +3,7 @@ * provided by the jz4780 and related SoCs. The power management * functionality could be exposed using a separate driver. * - * Copyright (C) 2017, 2018, 2020 Paul Boddie + * Copyright (C) 2017, 2018, 2020, 2021 Paul Boddie * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as @@ -472,11 +472,11 @@ switch (get_memory_source()) { case Source_mux_main: - return get_main_frequency(); + return get_main_frequency(); case Source_mux_pll_M: - return get_pll_frequency(Pll_control_M); + return get_pll_frequency(Pll_control_M); default: - return 0; + return 0; } } @@ -492,13 +492,13 @@ switch (get_cpu_source()) { case Source_mux_main: - return get_main_frequency(); + return get_main_frequency(); case Source_mux_pll_M: - return get_pll_frequency(Pll_control_M); + return get_pll_frequency(Pll_control_M); case Source_mux_pll_E: - return get_pll_frequency(Pll_control_E); + return get_pll_frequency(Pll_control_E); default: - return 0; + return 0; } } @@ -514,13 +514,13 @@ switch (get_hclock0_source()) { case Source_mux_main: - return get_main_frequency(); + return get_main_frequency(); case Source_mux_pll_M: - return get_pll_frequency(Pll_control_M); + return get_pll_frequency(Pll_control_M); case Source_mux_pll_E: - return get_pll_frequency(Pll_control_E); + return get_pll_frequency(Pll_control_E); default: - return 0; + return 0; } } @@ -536,13 +536,13 @@ switch (get_hclock2_source()) { case Source_mux_main: - return get_main_frequency(); + return get_main_frequency(); case Source_mux_pll_M: - return get_pll_frequency(Pll_control_M); + return get_pll_frequency(Pll_control_M); case Source_mux_realtime: - return _rtclk_freq; // "TCK" in the manual, RTCLK in Linux driver code + return _rtclk_freq; // "TCK" in the manual, RTCLK in Linux driver code default: - return 0; + return 0; } } @@ -564,13 +564,13 @@ switch (get_hdmi_source()) { case Source_main: - return get_main_frequency(); + return get_main_frequency(); case Source_pll_M: - return get_pll_frequency(Pll_control_M); + return get_pll_frequency(Pll_control_M); case Source_pll_V: - return get_pll_frequency(Pll_control_V); + return get_pll_frequency(Pll_control_V); default: - return 0; + return 0; } } @@ -603,13 +603,13 @@ switch (get_lcd_source(controller)) { case Source_main: - return get_main_frequency(); + return get_main_frequency(); case Source_pll_M: - return get_pll_frequency(Pll_control_M); + return get_pll_frequency(Pll_control_M); case Source_pll_V: - return get_pll_frequency(Pll_control_V); + return get_pll_frequency(Pll_control_V); default: - return 0; + return 0; } } @@ -666,13 +666,13 @@ switch (get_main_source()) { case Source_pll_A: - return get_pll_frequency(Pll_control_A); + return get_pll_frequency(Pll_control_A); case Source_external: - return _exclk_freq; + return _exclk_freq; case Source_realtime: - return _rtclk_freq; + return _rtclk_freq; default: - return 0; + return 0; } } @@ -708,22 +708,6 @@ return get_pclock_source_frequency() / get_pclock_divider(); } -// Clock frequency for the HDMI peripheral. - -uint32_t -Cpm_jz4780_chip::get_hdmi_frequency() -{ - return get_hdmi_source_frequency() / get_hdmi_divider(); -} - -// Clock frequency for the LCD0 or LCD1 controller. - -uint32_t -Cpm_jz4780_chip::get_lcd_pixel_frequency(uint8_t controller) -{ - return get_lcd_source_frequency(controller) / get_lcd_pixel_divider(controller); -} - // Clock frequency for the memory. uint32_t @@ -758,44 +742,67 @@ -void -Cpm_jz4780_chip::set_hdmi_frequency(uint32_t pclk) +uint32_t +Cpm_jz4780_chip::get_frequency(enum Clock_frequency_identifiers clock) { - // Switch to the video PLL and attempt to set the divider. + switch (clock) + { + // NOTE: Returning only the frequency for controller 0. + + case Clock_frequency_lcd_pixel: + return get_lcd_source_frequency(0) / get_lcd_pixel_divider(0); - set_hdmi_source(Source_pll_V); - pll_enable(Pll_control_V); - set_hdmi_divider(get_hdmi_source_frequency() / pclk); + case Clock_frequency_hdmi: + return get_hdmi_source_frequency() / get_hdmi_divider(); + + // NOTE: Consider a better error result. + + default: + return 0; + } } -// Set the pixel frequency. -// Unlike the jz4740, HCLK/AHB0 is used as the device frequency, with the pixel -// frequency being based on the selected clock source (SCLK_A, MPLL or VPLL). - void -Cpm_jz4780_chip::set_lcd_pixel_frequency(uint32_t pclk) +Cpm_jz4780_chip::set_frequency(enum Clock_frequency_identifiers clock, uint32_t frequency) { - // Switch to the video PLL and attempt to set the divider. + switch (clock) + { + // NOTE: HCLK/AHB0 must be 1.5 (for TFT) or 3 (for STN) times the pixel clock. + // NOTE: Here, the actual frequency value is ignored, but should at least be + // NOTE: tested. + + case Clock_frequency_lcd: + set_lcd_source(0, Source_pll_V); + set_lcd_source(1, Source_pll_V); + pll_enable(Pll_control_V); + break; + + // Unlike the JZ4740, HCLK/AHB0 is used as the device frequency, with the pixel + // frequency being based on the selected clock source (SCLK_A, MPLL or VPLL). + + case Clock_frequency_lcd_pixel: - set_lcd_source(0, Source_pll_V); - set_lcd_source(1, Source_pll_V); - pll_enable(Pll_control_V); - set_lcd_pixel_divider(0, get_lcd_source_frequency() / pclk); - set_lcd_pixel_divider(1, get_lcd_source_frequency() / pclk); -} + // Switch to the video PLL and attempt to set the divider. + + set_lcd_pixel_divider(0, get_lcd_source_frequency() / frequency); + set_lcd_pixel_divider(1, get_lcd_source_frequency() / frequency); + break; + + case Clock_frequency_hdmi: -// NOTE: Compatibility method. Probably needs reviewing. -// NOTE: HCLK/AHB0 must be 1.5 (for TFT) or 3 (for STN) times the pixel clock. + // Switch to the video PLL and attempt to set the divider. -void -Cpm_jz4780_chip::set_lcd_frequencies(uint32_t pclk, uint8_t ratio) -{ - (void) ratio; - set_lcd_pixel_frequency(pclk); + set_hdmi_source(Source_pll_V); + pll_enable(Pll_control_V); + set_hdmi_divider(get_hdmi_source_frequency() / frequency); + break; + + default: + break; + } } // NOTE: Empty method for compatibility. -// NOTE: It could potentially be combined with start_lcd. void Cpm_jz4780_chip::update_output_frequency() @@ -992,18 +999,6 @@ } uint32_t -jz4780_cpm_get_hdmi_frequency(void *cpm) -{ - return static_cast(cpm)->get_hdmi_frequency(); -} - -uint32_t -jz4780_cpm_get_lcd_pixel_frequency(void *cpm) -{ - return static_cast(cpm)->get_lcd_pixel_frequency(); -} - -uint32_t jz4780_cpm_get_memory_frequency(void *cpm) { return static_cast(cpm)->get_memory_frequency(); @@ -1041,22 +1036,16 @@ -void -jz4780_cpm_set_hdmi_frequency(void *cpm, uint32_t pclk) +uint32_t +jz4780_cpm_get_frequency(void *cpm, enum Clock_frequency_identifiers clock) { - static_cast(cpm)->set_hdmi_frequency(pclk); + return static_cast(cpm)->get_frequency(clock); } void -jz4780_cpm_set_lcd_pixel_frequency(void *cpm, uint32_t pclk) +jz4780_cpm_set_frequency(void *cpm, enum Clock_frequency_identifiers clock, uint32_t frequency) { - static_cast(cpm)->set_lcd_pixel_frequency(pclk); -} - -void -jz4780_cpm_set_lcd_frequencies(void *cpm, uint32_t pclk, uint8_t ratio) -{ - static_cast(cpm)->set_lcd_frequencies(pclk, ratio); + static_cast(cpm)->set_frequency(clock, frequency); } void diff -r 686488c38e1d -r 64fb2fa99680 pkg/landfall-examples/ci20_cpm/ci20_cpm.c --- a/pkg/landfall-examples/ci20_cpm/ci20_cpm.c Sat Jan 30 23:39:17 2021 +0100 +++ b/pkg/landfall-examples/ci20_cpm/ci20_cpm.c Sun Jan 31 00:49:22 2021 +0100 @@ -1,7 +1,7 @@ /* * (c) 2008-2009 Adam Lackorzynski * economic rights: Technische Universität Dresden (Germany) - * Copyright (C) 2017, 2018 Paul Boddie + * Copyright (C) 2017, 2018, 2021 Paul Boddie * * This file is part of TUD:OS and distributed under the terms of the * GNU General Public License 2. @@ -156,16 +156,16 @@ printf("LCD source: %d\n", jz4780_cpm_get_lcd_source(cpm)); printf(" LCD source frequency: %d\n", jz4780_cpm_get_lcd_source_frequency(cpm)); printf(" LCD pixel clock divider: %d\n", jz4780_cpm_get_lcd_pixel_divider(cpm)); - printf(" LCD pixel clock frequency: %d\n", jz4780_cpm_get_lcd_pixel_frequency(cpm)); + printf(" LCD pixel clock frequency: %d\n", jz4780_cpm_get_frequency(cpm, Clock_frequency_lcd_pixel)); /* Attempt to set the pixel clock frequency. */ - jz4780_cpm_set_lcd_pixel_frequency(cpm, 108000000); + jz4780_cpm_set_frequency(cpm, Clock_frequency_lcd_pixel, 108000000); printf("LCD source: %d\n", jz4780_cpm_get_lcd_source(cpm)); printf(" LCD source frequency: %d\n", jz4780_cpm_get_lcd_source_frequency(cpm)); printf(" LCD pixel clock divider: %d\n", jz4780_cpm_get_lcd_pixel_divider(cpm)); - printf(" LCD pixel clock frequency: %d\n", jz4780_cpm_get_lcd_pixel_frequency(cpm)); + printf(" LCD pixel clock frequency: %d\n", jz4780_cpm_get_frequency(cpm, Clock_frequency_lcd_pixel)); /* Attempt to set the peripheral clock frequency. */ diff -r 686488c38e1d -r 64fb2fa99680 pkg/landfall-examples/ci20_hdmi_i2c/ci20_hdmi_i2c.c --- a/pkg/landfall-examples/ci20_hdmi_i2c/ci20_hdmi_i2c.c Sat Jan 30 23:39:17 2021 +0100 +++ b/pkg/landfall-examples/ci20_hdmi_i2c/ci20_hdmi_i2c.c Sun Jan 31 00:49:22 2021 +0100 @@ -1,7 +1,7 @@ /* * Access the HDMI I2C peripheral on the MIPS Creator CI20 board. * - * Copyright (C) 2020 Paul Boddie + * Copyright (C) 2020, 2021 Paul Boddie * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as @@ -268,15 +268,15 @@ printf("VPLL frequency: %d\n", jz4780_cpm_get_vpll_frequency(cpm)); printf("HDMI divider: %d\n", jz4780_cpm_get_hdmi_divider(cpm)); - printf("HDMI frequency: %d\n", jz4780_cpm_get_hdmi_frequency(cpm)); + printf("HDMI frequency: %d\n", jz4780_cpm_get_frequency(cpm, Clock_frequency_hdmi)); - jz4780_cpm_stop_hdmi(cpm); - jz4780_cpm_set_hdmi_frequency(cpm, 27000000); + jz4780_cpm_stop_clock(cpm, Clock_hdmi); + jz4780_cpm_set_frequency(cpm, Clock_frequency_hdmi, 27000000); printf("HDMI divider: %d\n", jz4780_cpm_get_hdmi_divider(cpm)); - printf("HDMI frequency: %d\n", jz4780_cpm_get_hdmi_frequency(cpm)); + printf("HDMI frequency: %d\n", jz4780_cpm_get_frequency(cpm, Clock_frequency_hdmi)); - jz4780_cpm_start_hdmi(cpm); + jz4780_cpm_start_clock(cpm, Clock_hdmi); /* Configure pins. */ @@ -336,22 +336,22 @@ printf("LCD source: %d\n", jz4780_cpm_get_lcd_source(cpm)); printf("LCD divider: %d\n", jz4780_cpm_get_lcd_pixel_divider(cpm)); - printf("LCD frequency: %d\n", jz4780_cpm_get_lcd_pixel_frequency(cpm)); + printf("LCD frequency: %d\n", jz4780_cpm_get_frequency(cpm, Clock_frequency_lcd_pixel)); printf("Desired frequency: %d\n", jz4740_lcd_get_pixel_clock(lcd)); - jz4780_cpm_stop_lcd(cpm); - jz4780_cpm_set_lcd_frequencies(cpm, jz4740_lcd_get_pixel_clock(lcd), 3); + jz4780_cpm_stop_clock(cpm, Clock_lcd); + jz4780_cpm_set_frequency(cpm, Clock_frequency_lcd_pixel, jz4740_lcd_get_pixel_clock(lcd)); printf("LCD source: %d\n", jz4780_cpm_get_lcd_source(cpm)); printf("LCD divider: %d\n", jz4780_cpm_get_lcd_pixel_divider(cpm)); - printf("LCD frequency: %d\n", jz4780_cpm_get_lcd_pixel_frequency(cpm)); + printf("LCD frequency: %d\n", jz4780_cpm_get_frequency(cpm, Clock_frequency_lcd_pixel)); printf("AHB0 frequency: %d\n", jz4780_cpm_get_hclock0_frequency(cpm)); /* With the LCD pixel clock set up, bring up the HDMI. */ printf("Enable HDMI output...\n"); - jz4780_hdmi_enable(hdmi, jz4780_cpm_get_lcd_pixel_frequency(cpm)); + jz4780_hdmi_enable(hdmi, jz4780_cpm_get_frequency(cpm, Clock_frequency_lcd_pixel)); /* Allocate descriptors and framebuffer at 2**8 == 256 byte == 64 word alignment. */ @@ -417,7 +417,7 @@ printf("Start LCD clock and initialise LCD...\n"); - jz4780_cpm_start_lcd(cpm); + jz4780_cpm_start_clock(cpm, Clock_lcd); l4_sleep(1); // 1ms == 1000us jz4740_lcd_disable(lcd);